diff --git a/siteupdate/cplusplus/classes/DatacheckEntry.cpp b/siteupdate/cplusplus/classes/DatacheckEntry.cpp index 5151cf2d..0530a3f3 100644 --- a/siteupdate/cplusplus/classes/DatacheckEntry.cpp +++ b/siteupdate/cplusplus/classes/DatacheckEntry.cpp @@ -3,9 +3,9 @@ class DatacheckEntry route is a pointer to the route with a datacheck error - labels is a list of labels that are related to the error (such - as the endpoints of a too-long segment or the three points that - form a sharp angle) + label1, label2 & label3 are labels that are related to the error + (such as the endpoints of a too-long segment or the three points + that form a sharp angle) code is the error code | info is additional string, one of: | information, if used: @@ -36,7 +36,7 @@ class DatacheckEntry NONTERMINAL_UNDERSCORE | OUT_OF_BOUNDS | coordinate pair SHARP_ANGLE | angle in degrees - US_BANNER | + US_LETTER | VISIBLE_DISTANCE | distance in miles VISIBLE_HIDDEN_COLOC | hidden point at same coordinates diff --git a/siteupdate/cplusplus/classes/Route/Route.h b/siteupdate/cplusplus/classes/Route/Route.h index e099d6db..3f6a4a8d 100644 --- a/siteupdate/cplusplus/classes/Route/Route.h +++ b/siteupdate/cplusplus/classes/Route/Route.h @@ -65,7 +65,7 @@ class Route Route(std::string &, HighwaySystem *, ErrorList &, std::unordered_map &); std::string str(); - void read_wpt(WaypointQuadtree *, ErrorList *, std::string, DatacheckEntryList *, std::unordered_set *); + void read_wpt(WaypointQuadtree *, ErrorList *, std::string, bool, DatacheckEntryList *, std::unordered_set *); void print_route(); HighwaySegment* find_segment_by_waypoints(Waypoint*, Waypoint*); std::string chopped_rtes_line(); diff --git a/siteupdate/cplusplus/classes/Route/read_wpt.cpp b/siteupdate/cplusplus/classes/Route/read_wpt.cpp index 0fe0e1cb..4377c79b 100644 --- a/siteupdate/cplusplus/classes/Route/read_wpt.cpp +++ b/siteupdate/cplusplus/classes/Route/read_wpt.cpp @@ -1,5 +1,5 @@ void Route::read_wpt -( WaypointQuadtree *all_waypoints, ErrorList *el, std::string path, +( WaypointQuadtree *all_waypoints, ErrorList *el, std::string path, bool usa_flag, DatacheckEntryList *datacheckerrors, std::unordered_set *all_wpt_files ) { /* read data into the Route's waypoint list from a .wpt file */ @@ -72,8 +72,11 @@ void Route::read_wpt // checks for visible points if (!w->is_hidden) { const char *slash = strchr(w->label.data(), '/'); - w->bus_with_i(datacheckerrors); - w->interstate_no_hyphen(datacheckerrors); + if (usa_flag && w->label.size() >= 2) + { w->bus_with_i(datacheckerrors); + w->interstate_no_hyphen(datacheckerrors); + w->us_letter(datacheckerrors); + } w->label_invalid_ends(datacheckerrors); w->label_looks_hidden(datacheckerrors); w->label_parens(datacheckerrors); diff --git a/siteupdate/cplusplus/classes/Waypoint/Waypoint.cpp b/siteupdate/cplusplus/classes/Waypoint/Waypoint.cpp index e8d67fe0..d1c4ca9e 100644 --- a/siteupdate/cplusplus/classes/Waypoint/Waypoint.cpp +++ b/siteupdate/cplusplus/classes/Waypoint/Waypoint.cpp @@ -389,7 +389,7 @@ inline void Waypoint::bus_with_i(DatacheckEntryList *datacheckerrors) { // look for I-xx with Bus instead of BL or BS const char *c = label.data(); if (*c == '*') c++; - if (*c++ != 'I' || *c++ != '-' || route->system->country->first != "USA") return; + if (*c++ != 'I' || *c++ != '-') return; if (*c < '0' || *c > '9') return; while (*c >= '0' && *c <= '9') c++; if ( *c == 'E' || *c == 'W' || *c == 'C' || *c == 'N' || *c == 'S' @@ -401,12 +401,10 @@ inline void Waypoint::bus_with_i(DatacheckEntryList *datacheckerrors) } inline void Waypoint::interstate_no_hyphen(DatacheckEntryList *datacheckerrors) -{ if (route->system->country->first == "USA" && label.size() >= 2) - { const char *c = label.data(); - if (c[0] == 'T' && c[1] == 'o') c += 2; - if (c[0] == 'I' && isdigit(c[1])) - datacheckerrors->add(route, label, "", "", "INTERSTATE_NO_HYPHEN", ""); - } +{ const char *c = label[0] == '*' ? label.data()+1 : label.data(); + if (c[0] == 'T' && c[1] == 'o') c += 2; + if (c[0] == 'I' && isdigit(c[1])) + datacheckerrors->add(route, label, "", "", "INTERSTATE_NO_HYPHEN", ""); } inline void Waypoint::label_invalid_ends(DatacheckEntryList *datacheckerrors) @@ -457,15 +455,7 @@ inline void Waypoint::label_parens(DatacheckEntryList *datacheckerrors) inline void Waypoint::label_selfref(DatacheckEntryList *datacheckerrors, const char *slash) { // looking for the route within the label - //match_start = w.label.find(r.route) - //if match_start >= 0: - // we have a potential match, just need to make sure if the route - // name ends with a number that the matched substring isn't followed - // by more numbers (e.g., NY50 is an OK label in NY5) - // if len(r.route) + match_start == len(w.label) or \ - // not w.label[len(r.route) + match_start].isdigit(): // partially complete "references own route" -- too many FP - //or re.fullmatch('.*/'+r.route+'.*',w.label[w.label) : // first check for number match after a slash, if there is one if (slash && route->route.back() >= '0' && route->route.back() <= '9') { int digit_starts = route->route.size()-1; @@ -530,11 +520,16 @@ inline void Waypoint::underscore_datachecks(DatacheckEntryList *datacheckerrors, } } -// look for USxxxA but not USxxxAlt, B/Bus (others?) -//if re.fullmatch('US[0-9]+A.*', w.label) and not re.fullmatch('US[0-9]+Alt.*', w.label) or \ -// re.fullmatch('US[0-9]+B.*', w.label) and \ -// not (re.fullmatch('US[0-9]+Bus.*', w.label) or re.fullmatch('US[0-9]+Byp.*', w.label)): -// datacheckerrors.append(DatacheckEntry(r,[w.label],'US_BANNER')) +inline void Waypoint::us_letter(DatacheckEntryList *datacheckerrors) +{ // look for USxxxA but not USxxxAlt, B/Bus/Byp + const char* c = label[0] == '*' ? label.data()+1 : label.data(); + if (*c++ != 'U' || *c++ != 'S') return; + if (*c < '0' || *c++ > '9') return; + while (*c >= '0' && *c <= '9') c++; + if (*c < 'A' || *c++ > 'B') return; + if (*c == 0 || *c == '/' || *c == '_' || *c == '(') + datacheckerrors->add(route, label, "", "", "US_LETTER", ""); +} inline void Waypoint::visible_distance(DatacheckEntryList *datacheckerrors, char *fstr, double &vis_dist, Waypoint *&last_visible) { // complete visible distance check, omit report for active diff --git a/siteupdate/cplusplus/classes/Waypoint/Waypoint.h b/siteupdate/cplusplus/classes/Waypoint/Waypoint.h index 23a5d09f..c1ebf0ad 100644 --- a/siteupdate/cplusplus/classes/Waypoint/Waypoint.h +++ b/siteupdate/cplusplus/classes/Waypoint/Waypoint.h @@ -54,5 +54,6 @@ class Waypoint inline void label_slashes(DatacheckEntryList *, const char *); inline void lacks_generic(DatacheckEntryList *); inline void underscore_datachecks(DatacheckEntryList *, const char *); + inline void us_letter(DatacheckEntryList *); inline void visible_distance(DatacheckEntryList *, char *, double &, Waypoint *&); }; diff --git a/siteupdate/cplusplus/siteupdate.cpp b/siteupdate/cplusplus/siteupdate.cpp index 87d81443..5490812e 100644 --- a/siteupdate/cplusplus/siteupdate.cpp +++ b/siteupdate/cplusplus/siteupdate.cpp @@ -285,8 +285,9 @@ int main(int argc, char *argv[]) #else for (HighwaySystem* h : highway_systems) { std::cout << h->systemname << std::flush; + bool usa_flag = h->country->first == "USA"; for (Route& r : h->route_list) - r.read_wpt(&all_waypoints, &el, args.highwaydatapath+"/hwy_data", datacheckerrors, &all_wpt_files); + r.read_wpt(&all_waypoints, &el, args.highwaydatapath+"/hwy_data", usa_flag, datacheckerrors, &all_wpt_files); std::cout << "!" << std::endl; } #endif @@ -934,7 +935,7 @@ int main(int argc, char *argv[]) "LABEL_INVALID_CHAR", "LABEL_PARENS", "LABEL_SLASHES", "LABEL_TOO_LONG", "LABEL_UNDERSCORES", "LONG_UNDERSCORE", "MALFORMED_LAT", "MALFORMED_LON", "MALFORMED_URL", - "NONTERMINAL_UNDERSCORE" + "NONTERMINAL_UNDERSCORE", "US_LETTER" }); while (getline(file, line)) { // trim DOS newlines & trailing whitespace diff --git a/siteupdate/cplusplus/threads/ReadWptThread.cpp b/siteupdate/cplusplus/threads/ReadWptThread.cpp index 712111f7..f8a20099 100644 --- a/siteupdate/cplusplus/threads/ReadWptThread.cpp +++ b/siteupdate/cplusplus/threads/ReadWptThread.cpp @@ -16,8 +16,9 @@ void ReadWptThread //printf("ReadWptThread %02i (*it)++\n", id); fflush(stdout); hs_mtx->unlock(); std::cout << h->systemname << std::flush; + bool usa_flag = h->country->first == "USA"; for (Route &r : h->route_list) - r.read_wpt(all_waypoints, el, path, datacheckerrors, all_wpt_files); + r.read_wpt(all_waypoints, el, path, usa_flag, datacheckerrors, all_wpt_files); std::cout << "!" << std::endl; } } diff --git a/siteupdate/python-teresco/siteupdate.py b/siteupdate/python-teresco/siteupdate.py index 45f914e0..fc2a0bc1 100755 --- a/siteupdate/python-teresco/siteupdate.py +++ b/siteupdate/python-teresco/siteupdate.py @@ -1579,7 +1579,7 @@ class DatacheckEntry: NONTERMINAL_UNDERSCORE | OUT_OF_BOUNDS | coordinate pair SHARP_ANGLE | angle in degrees - US_BANNER | + US_LETTER | VISIBLE_DISTANCE | distance in miles VISIBLE_HIDDEN_COLOC | hidden point at same coordinates @@ -3549,7 +3549,7 @@ def run(self): 'LABEL_INVALID_CHAR', 'LABEL_PARENS', 'LABEL_SLASHES', 'LABEL_TOO_LONG', 'LABEL_UNDERSCORES', 'LONG_UNDERSCORE', 'MALFORMED_LAT', 'MALFORMED_LON', 'MALFORMED_URL', - 'NONTERMINAL_UNDERSCORE' ] + 'NONTERMINAL_UNDERSCORE', 'US_LETTER' ] for line in lines: line=line.strip() if len(line) == 0: @@ -3817,6 +3817,7 @@ def run(self): # perform most datachecks here (list initialized above) for h in highway_systems: print(".",end="",flush=True) + usa_flag = h.country == "USA" for r in h.route_list: # set of tuples to be used for finding duplicate coordinates coords_used = set() @@ -3886,15 +3887,7 @@ def run(self): visible_distance = 0.0 # looking for the route within the label - #match_start = w.label.find(r.route) - #if match_start >= 0: - # we have a potential match, just need to make sure if the route - # name ends with a number that the matched substring isn't followed - # by more numbers (e.g., NY50 is an OK label in NY5) - # if len(r.route) + match_start == len(w.label) or \ - # not w.label[len(r.route) + match_start].isdigit(): # partially complete "references own route" -- too many FP - #or re.fullmatch('.*/'+r.route+'.*',w.label[w.label) : # first check for number match after a slash, if there is one selfref_found = False if '/' in w.label and r.route[-1].isdigit(): @@ -3909,7 +3902,6 @@ def run(self): selfref_found = True if '_' in w.label[w.label.index('/')+1:] and w.label[w.label.index('/')+1:w.label.rindex('_')] == r.route: selfref_found = True - # now the remaining checks if selfref_found or r.route+r.banner == w.label or re.fullmatch(r.route+r.banner+'[_/].*',w.label): datacheckerrors.append(DatacheckEntry(r,[w.label],'LABEL_SELFREF')) @@ -3960,20 +3952,22 @@ def run(self): datacheckerrors.append(DatacheckEntry(r,[w.label],'LACKS_GENERIC')) # USA-only datachecks - if w.route.system.country == "USA" and len(w.label) >= 2: + if usa_flag and len(w.label) >= 2: # look for I-xx with Bus instead of BL or BS if re.fullmatch('\*?I\-[0-9]+[EeWwCcNnSs]?[Bb][Uu][Ss].*', w.label): datacheckerrors.append(DatacheckEntry(r,[w.label],'BUS_WITH_I')) # look for Ixx without hyphen - c = 2 if (w.label.startswith("To") and len(w.label) > 2) else 0 - if w.label[c] == 'I' and w.label[c+1].isdigit(): + c = 1 if w.label[0] == '*' else 0 + if w.label[c:c+2] == "To": + c += 2; + if len(w.label) >= c+2 and w.label[c] == 'I' and w.label[c+1].isdigit(): datacheckerrors.append(DatacheckEntry(r,[w.label],'INTERSTATE_NO_HYPHEN')) - - # look for USxxxA but not USxxxAlt, B/Bus (others?) - ##if re.fullmatch('US[0-9]+A.*', w.label) and not re.fullmatch('US[0-9]+Alt.*', w.label) or \ - ## re.fullmatch('US[0-9]+B.*', w.label) and \ - ## not (re.fullmatch('US[0-9]+Bus.*', w.label) or re.fullmatch('US[0-9]+Byp.*', w.label)): - ## datacheckerrors.append(DatacheckEntry(r,[w.label],'US_BANNER')) + # look for USxxxA but not USxxxAlt, B/Bus/Byp + # Eric's paraphrase of Jim's original criteria + # if re.fullmatch('\*?US[0-9]+[AB].*', w.label) and not re.fullmatch('\*?US[0-9]+Alt.*|\*?US[0-9]+Bus.*|\*?US[0-9]+Byp.*', w.label): + # Instead, let's cast a narrower net + if re.fullmatch('\*?US[0-9]+[AB]|\*?US[0-9]+[AB][/_(].*', w.label): + datacheckerrors.append(DatacheckEntry(r,[w.label],'US_LETTER')) prev_w = w