Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions siteupdate/cplusplus/classes/DatacheckEntry.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -17,6 +17,7 @@ class DatacheckEntry
DUPLICATE_LABEL |
HIDDEN_JUNCTION | number of incident edges in TM master graph
HIDDEN_TERMINUS |
INTERSTATE_NO_HYPHEN |
INVALID_FINAL_CHAR | final character in label
INVALID_FIRST_CHAR | first character in label other than *
LABEL_INVALID_CHAR |
Expand Down
15 changes: 8 additions & 7 deletions siteupdate/cplusplus/classes/Route/read_wpt.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -71,16 +71,17 @@ void Route::read_wpt
}
// checks for visible points
if (!w->is_hidden)
{ w->visible_distance(datacheckerrors, fstr, vis_dist, last_visible);
const char *slash = strchr(w->label.data(), '/');
w->label_selfref(datacheckerrors, slash);
w->label_slashes(datacheckerrors, slash);
w->underscore_datachecks(datacheckerrors, slash);
w->label_parens(datacheckerrors);
w->label_invalid_ends(datacheckerrors);
{ const char *slash = strchr(w->label.data(), '/');
w->bus_with_i(datacheckerrors);
w->interstate_no_hyphen(datacheckerrors);
w->label_invalid_ends(datacheckerrors);
w->label_looks_hidden(datacheckerrors);
w->label_parens(datacheckerrors);
w->label_selfref(datacheckerrors, slash);
w->label_slashes(datacheckerrors, slash);
w->lacks_generic(datacheckerrors);
w->underscore_datachecks(datacheckerrors, slash);
w->visible_distance(datacheckerrors, fstr, vis_dist, last_visible);
}
}
delete[] wptdata;
Expand Down
175 changes: 92 additions & 83 deletions siteupdate/cplusplus/classes/Waypoint/Waypoint.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -305,6 +305,16 @@ bool Waypoint::label_references_route(Route *r, DatacheckEntryList *datacheckerr

/* Datacheck */

inline void Waypoint::distance_update(DatacheckEntryList *datacheckerrors, char *fstr, double &vis_dist, Waypoint *prev_w)
{ // visible distance update, and last segment length check
double last_distance = distance_to(prev_w);
vis_dist += last_distance;
if (last_distance > 20)
{ sprintf(fstr, "%.2f", last_distance);
datacheckerrors->add(route, prev_w->label, label, "", "LONG_SEGMENT", fstr);
}
}

inline void Waypoint::duplicate_coords(DatacheckEntryList *datacheckerrors, std::unordered_set<Waypoint*> &coords_used, char *fstr)
{ // duplicate coordinates
Waypoint *w;
Expand All@@ -320,6 +330,25 @@ inline void Waypoint::duplicate_coords(DatacheckEntryList *datacheckerrors, std:
}
}

inline void Waypoint::label_invalid_char(DatacheckEntryList *datacheckerrors)
{ // look for labels with invalid characters
if (label == "*")
datacheckerrors->add(route, label, "", "", "LABEL_INVALID_CHAR", "");
else for (const char *c = label.data(); *c; c++)
if ((*c == 42 || *c == 43) && c > label.data()
|| (*c < 40) || (*c == 44) || (*c > 57 && *c < 65)
|| (*c == 96) || (*c > 122) || (*c > 90 && *c < 95))
datacheckerrors->add(route, label, "", "", "LABEL_INVALID_CHAR", "");
for (std::string& lbl : alt_labels)
if (lbl == "*")
datacheckerrors->add(route, lbl, "", "", "LABEL_INVALID_CHAR", "");
else for (const char *c = lbl.data(); *c; c++)
if (*c == '+' && c > lbl.data() || *c == '*' && (c > lbl.data()+1 || lbl[0] != '+')
|| (*c < 40) || (*c == 44) || (*c > 57 && *c < 65)
|| (*c == 96) || (*c > 122) || (*c > 90 && *c < 95))
datacheckerrors->add(route, lbl, "", "", "LABEL_INVALID_CHAR", "");
}

inline bool Waypoint::label_too_long(DatacheckEntryList *datacheckerrors)
{ // label longer than the DB can store
if (label.size() > DBFieldLength::label)
Expand All@@ -346,16 +375,6 @@ inline bool Waypoint::label_too_long(DatacheckEntryList *datacheckerrors)
return 0;
}

inline void Waypoint::lacks_generic(DatacheckEntryList *datacheckerrors)
{ // label lacks generic highway type
const char* c = label[0] == '*' ? label.data()+1 : label.data();
if ( (*c == 'O' || *c == 'o')
&& (*(c+1) == 'l' || *(c+1) == 'L')
&& (*(c+2) == 'd' || *(c+2) == 'D')
&& *(c+3) >= '0' && *(c+3) <= '9')
datacheckerrors->add(route, label, "", "", "LACKS_GENERIC", "");
}

inline void Waypoint::out_of_bounds(DatacheckEntryList *datacheckerrors, char *fstr)
{ // out-of-bounds coords
if (lat > 90 || lat < -90 || lng > 180 || lng < -180)
Expand All@@ -364,34 +383,13 @@ inline void Waypoint::out_of_bounds(DatacheckEntryList *datacheckerrors, char *f
}
}

inline void Waypoint::distance_update(DatacheckEntryList *datacheckerrors, char *fstr, double &vis_dist, Waypoint *prev_w)
{ // visible distance update, and last segment length check
double last_distance = distance_to(prev_w);
vis_dist += last_distance;
if (last_distance > 20)
{ sprintf(fstr, "%.2f", last_distance);
datacheckerrors->add(route, prev_w->label, label, "", "LONG_SEGMENT", fstr);
}
}

/* checks for visible points */

inline void Waypoint::visible_distance(DatacheckEntryList *datacheckerrors, char *fstr, double &vis_dist, Waypoint *&last_visible)
{ // complete visible distance check, omit report for active
// systems to reduce clutter
if (vis_dist > 10 && !route->system->active())
{ sprintf(fstr, "%.2f", vis_dist);
datacheckerrors->add(route, last_visible->label, label, "", "VISIBLE_DISTANCE", fstr);
}
last_visible = this;
vis_dist = 0;
}

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->region->country->first != "USA") return;
if (*c++ != 'I' || *c++ != '-' || route->system->country->first != "USA") return;
if (*c < '0' || *c > '9') return;
while (*c >= '0' && *c <= '9') c++;
if ( *c == 'E' || *c == 'W' || *c == 'C' || *c == 'N' || *c == 'S'
Expand All@@ -402,6 +400,25 @@ inline void Waypoint::bus_with_i(DatacheckEntryList *datacheckerrors)
datacheckerrors->add(route, label, "", "", "BUS_WITH_I", "");
}

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", "");
}
}

inline void Waypoint::label_invalid_ends(DatacheckEntryList *datacheckerrors)
{ // look for labels with invalid first or final characters
const char *c = label.data();
while (*c == '*') c++;
if (*c == '_' || *c == '/' || *c == '(')
datacheckerrors->add(route, label, "", "", "INVALID_FIRST_CHAR", std::string(1, *c));
if (label.back() == '_' || label.back() == '/')
datacheckerrors->add(route, label, "", "", "INVALID_FINAL_CHAR", std::string(1, label.back()));
}

inline void Waypoint::label_looks_hidden(DatacheckEntryList *datacheckerrors)
{ // look for labels that look like hidden waypoints but which aren't hidden
if (label.size() != 7) return;
Expand All@@ -415,35 +432,6 @@ inline void Waypoint::label_looks_hidden(DatacheckEntryList *datacheckerrors)
datacheckerrors->add(route, label, "", "", "LABEL_LOOKS_HIDDEN", "");
}

inline void Waypoint::label_invalid_char(DatacheckEntryList *datacheckerrors)
{ // look for labels with invalid characters
if (label == "*")
datacheckerrors->add(route, label, "", "", "LABEL_INVALID_CHAR", "");
else for (const char *c = label.data(); *c; c++)
if ((*c == 42 || *c == 43) && c > label.data()
|| (*c < 40) || (*c == 44) || (*c > 57 && *c < 65)
|| (*c == 96) || (*c > 122) || (*c > 90 && *c < 95))
datacheckerrors->add(route, label, "", "", "LABEL_INVALID_CHAR", "");
for (std::string& lbl : alt_labels)
if (lbl == "*")
datacheckerrors->add(route, lbl, "", "", "LABEL_INVALID_CHAR", "");
else for (const char *c = lbl.data(); *c; c++)
if (*c == '+' && c > lbl.data() || *c == '*' && (c > lbl.data()+1 || lbl[0] != '+')
|| (*c < 40) || (*c == 44) || (*c > 57 && *c < 65)
|| (*c == 96) || (*c > 122) || (*c > 90 && *c < 95))
datacheckerrors->add(route, lbl, "", "", "LABEL_INVALID_CHAR", "");
}

inline void Waypoint::label_invalid_ends(DatacheckEntryList *datacheckerrors)
{ // look for labels with invalid first or final characters
const char *c = label.data();
while (*c == '*') c++;
if (*c == '_' || *c == '/' || *c == '(')
datacheckerrors->add(route, label, "", "", "INVALID_FIRST_CHAR", std::string(1, *c));
if (label.back() == '_' || label.back() == '/')
datacheckerrors->add(route, label, "", "", "INVALID_FINAL_CHAR", std::string(1, label.back()));
}

inline void Waypoint::label_parens(DatacheckEntryList *datacheckerrors)
{ // look for parenthesis balance in label
int parens = 0;
Expand All@@ -467,28 +455,6 @@ inline void Waypoint::label_parens(DatacheckEntryList *datacheckerrors)
datacheckerrors->add(route, label, "", "", "LABEL_PARENS", "");
}

inline void Waypoint::underscore_datachecks(DatacheckEntryList *datacheckerrors, const char *slash)
{ const char *underscore = strchr(label.data(), '_');
if (underscore)
{ // look for too many underscores in label
if (strchr(underscore+1, '_'))
datacheckerrors->add(route, label, "", "", "LABEL_UNDERSCORES", "");
// look for too many characters after underscore in label
if (label.data()+label.size() > underscore+4)
if (label.back() > 'Z' || label.back() < 'A' || label.data()+label.size() > underscore+5)
datacheckerrors->add(route, label, "", "", "LONG_UNDERSCORE", "");
// look for labels with a slash after an underscore
if (slash > underscore)
datacheckerrors->add(route, label, "", "", "NONTERMINAL_UNDERSCORE", "");
}
}

inline void Waypoint::label_slashes(DatacheckEntryList *datacheckerrors, const char *slash)
{ // look for too many slashes in label
if (slash && strchr(slash+1, '/'))
datacheckerrors->add(route, label, "", "", "LABEL_SLASHES", "");
}

inline void Waypoint::label_selfref(DatacheckEntryList *datacheckerrors, const char *slash)
{ // looking for the route within the label
//match_start = w.label.find(r.route)
Expand DownExpand Up@@ -532,8 +498,51 @@ inline void Waypoint::label_selfref(DatacheckEntryList *datacheckerrors, const c
datacheckerrors->add(route, label, "", "", "LABEL_SELFREF", "");
}

inline void Waypoint::label_slashes(DatacheckEntryList *datacheckerrors, const char *slash)
{ // look for too many slashes in label
if (slash && strchr(slash+1, '/'))
datacheckerrors->add(route, label, "", "", "LABEL_SLASHES", "");
}

inline void Waypoint::lacks_generic(DatacheckEntryList *datacheckerrors)
{ // label lacks generic highway type
const char* c = label[0] == '*' ? label.data()+1 : label.data();
if ( (*c == 'O' || *c == 'o')
&& (*(c+1) == 'l' || *(c+1) == 'L')
&& (*(c+2) == 'd' || *(c+2) == 'D')
&& *(c+3) >= '0' && *(c+3) <= '9')
datacheckerrors->add(route, label, "", "", "LACKS_GENERIC", "");
}

inline void Waypoint::underscore_datachecks(DatacheckEntryList *datacheckerrors, const char *slash)
{ const char *underscore = strchr(label.data(), '_');
if (underscore)
{ // look for too many underscores in label
if (strchr(underscore+1, '_'))
datacheckerrors->add(route, label, "", "", "LABEL_UNDERSCORES", "");
// look for too many characters after underscore in label
if (label.data()+label.size() > underscore+4)
if (label.back() > 'Z' || label.back() < 'A' || label.data()+label.size() > underscore+5)
datacheckerrors->add(route, label, "", "", "LONG_UNDERSCORE", "");
// look for labels with a slash after an underscore
if (slash > underscore)
datacheckerrors->add(route, label, "", "", "NONTERMINAL_UNDERSCORE", "");
}
}

// 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::visible_distance(DatacheckEntryList *datacheckerrors, char *fstr, double &vis_dist, Waypoint *&last_visible)
{ // complete visible distance check, omit report for active
// systems to reduce clutter
if (vis_dist > 10 && !route->system->active())
{ sprintf(fstr, "%.2f", vis_dist);
datacheckerrors->add(route, last_visible->label, label, "", "VISIBLE_DISTANCE", fstr);
}
last_visible = this;
vis_dist = 0;
}
13 changes: 7 additions & 6 deletions siteupdate/cplusplus/classes/Waypoint/Waypoint.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -39,19 +39,20 @@ class Waypoint
bool label_references_route(Route *, DatacheckEntryList *);

// Datacheck
inline void distance_update(DatacheckEntryList *, char *, double &, Waypoint *);
inline void duplicate_coords(DatacheckEntryList *, std::unordered_set<Waypoint*> &, char *);
inline void label_invalid_char(DatacheckEntryList *);
inline bool label_too_long(DatacheckEntryList *);
inline void out_of_bounds(DatacheckEntryList *, char *);
inline void distance_update(DatacheckEntryList *, char *, double &, Waypoint *);
// checks for visible points
inline void visible_distance(DatacheckEntryList *, char *, double &, Waypoint *&);
inline void bus_with_i(DatacheckEntryList *);
inline void label_looks_hidden(DatacheckEntryList *);
inline void label_invalid_char(DatacheckEntryList *);
inline void interstate_no_hyphen(DatacheckEntryList *);
inline void label_invalid_ends(DatacheckEntryList *);
inline void label_looks_hidden(DatacheckEntryList *);
inline void label_parens(DatacheckEntryList *);
inline void label_slashes(DatacheckEntryList *, const char *);
inline void label_selfref(DatacheckEntryList *, const char *);
inline bool label_too_long(DatacheckEntryList *);
inline void label_slashes(DatacheckEntryList *, const char *);
inline void lacks_generic(DatacheckEntryList *);
inline void underscore_datachecks(DatacheckEntryList *, const char *);
inline void visible_distance(DatacheckEntryList *, char *, double &, Waypoint *&);
};
3 changes: 2 additions & 1 deletion siteupdate/cplusplus/siteupdate.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -930,7 +930,8 @@ int main(int argc, char *argv[])
list<array<string, 6>> datacheckfps;
unordered_set<string> datacheck_always_error
({ "BAD_ANGLE", "DISCONNECTED_ROUTE", "DUPLICATE_LABEL",
"HIDDEN_TERMINUS", "INVALID_FINAL_CHAR", "INVALID_FIRST_CHAR",
"HIDDEN_TERMINUS", "INTERSTATE_NO_HYPHEN",
"INVALID_FINAL_CHAR", "INVALID_FIRST_CHAR",
"LABEL_INVALID_CHAR", "LABEL_PARENS", "LABEL_SLASHES",
"LABEL_TOO_LONG", "LABEL_UNDERSCORES", "LONG_UNDERSCORE",
"MALFORMED_LAT", "MALFORMED_LON", "MALFORMED_URL",
Expand Down
18 changes: 13 additions & 5 deletions siteupdate/python-teresco/siteupdate.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -1559,6 +1559,7 @@ class DatacheckEntry:
DUPLICATE_LABEL |
HIDDEN_JUNCTION | number of incident edges in TM master graph
HIDDEN_TERMINUS |
INTERSTATE_NO_HYPHEN |
INVALID_FINAL_CHAR | final character in label
INVALID_FIRST_CHAR | first character in label other than *
LABEL_INVALID_CHAR |
Expand DownExpand Up@@ -3543,7 +3544,8 @@ def run(self):
lines.pop(0) # ignore header line
datacheckfps = []
datacheck_always_error = [ 'BAD_ANGLE', 'DISCONNECTED_ROUTE', 'DUPLICATE_LABEL',
'HIDDEN_TERMINUS', 'INVALID_FINAL_CHAR', 'INVALID_FIRST_CHAR',
'HIDDEN_TERMINUS', 'INTERSTATE_NO_HYPHEN',
'INVALID_FINAL_CHAR', 'INVALID_FIRST_CHAR',
'LABEL_INVALID_CHAR', 'LABEL_PARENS', 'LABEL_SLASHES',
'LABEL_TOO_LONG', 'LABEL_UNDERSCORES', 'LONG_UNDERSCORE',
'MALFORMED_LAT', 'MALFORMED_LON', 'MALFORMED_URL',
Expand DownExpand Up@@ -3948,10 +3950,6 @@ def run(self):
w.label.index('/') > w.label.index('_'):
datacheckerrors.append(DatacheckEntry(r,[w.label],'NONTERMINAL_UNDERSCORE'))

# look for I-xx with Bus instead of BL or BS
if re.fullmatch('\*?I\-[0-9]+[EeWwCcNnSs]?[Bb][Uu][Ss].*', w.label) and all_regions[w.route.region][2] == "USA":
datacheckerrors.append(DatacheckEntry(r,[w.label],'BUS_WITH_I'))

# look for labels that look like hidden waypoints but
# which aren't hidden
if re.fullmatch('X[0-9][0-9][0-9][0-9][0-9][0-9]', w.label):
Expand All@@ -3961,6 +3959,16 @@ def run(self):
if re.fullmatch('^\*?[Oo][lL][dD][0-9].*', w.label):
datacheckerrors.append(DatacheckEntry(r,[w.label],'LACKS_GENERIC'))

# USA-only datachecks
if w.route.system.country == "USA" 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():
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 \
Expand Down