From e3ce0c58871e429e9f29b8c2cb48db29fd1aeea7 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Wed, 18 May 2016 21:41:52 +0200 Subject: [PATCH] Add fuzzy matching for bearings and intersections list --- features/guidance/intersections.feature | 12 ++-- features/support/data_classes.js | 79 +++++++++++++++++++++++-- features/testbot/bearing_param.feature | 4 +- 3 files changed, 81 insertions(+), 14 deletions(-) diff --git a/features/guidance/intersections.feature b/features/guidance/intersections.feature index e73021402..531c85166 100644 --- a/features/guidance/intersections.feature +++ b/features/guidance/intersections.feature @@ -125,10 +125,10 @@ Feature: Intersections Data | hd | | When I route I should get - | waypoints | route | turns | intersections | - | e,f | ea,fb,fb | depart,abcda-exit-1,arrive | true:180;false:0 false:150 true:210,false:30 true:150 true:270;true:90 | - | e,g | ea,gc,gc | depart,abcda-exit-2,arrive | true:180;false:0 false:150 true:210,false:30 true:150 true:270,true:30 true:180 false:330;true:0 | + | waypoints | route | turns | intersections | + | e,f | ea,fb,fb | depart,abcda-exit-1,arrive | true:180;false:0 false:150 true:210,false:30 true:150 true:270;true:90 | + | e,g | ea,gc,gc | depart,abcda-exit-2,arrive | true:180;false:0 false:150 true:210,false:30 true:150 true:270,true:30 true:180 false:330;true:0| | e,h | ea,hd,hd | depart,abcda-exit-3,arrive | true:180;false:0 false:150 true:210,false:30 true:150 true:270,true:30 true:180 false:330,true:90 false:210 true:330;true:270 | - | e,2 | ea,abcda,abcda | depart,abcda-exit-undefined,arrive | true:180;false:0 false:150 true:210,false:30 true:150 true:270;true:326 | - | 1,g | abcda,gc,gc | depart,abcda-exit-2,arrive | true:214;true:214,false:30 true:150 true:270,true:30 true:180 false:330;true:0 | - | 1,3 | abcda,abcda | depart,arrive | true:214,false:30 true:150 true:270,true:30 true:180 false:330;true:214 | + | e,2 | ea,abcda,abcda | depart,abcda-exit-undefined,arrive | true:180;false:0 false:150 true:210,false:30 true:150 true:270;true:327 +-1| + | 1,g | abcda,gc,gc | depart,abcda-exit-2,arrive | true:214;true:214,false:30 true:150 true:270,true:30 true:180 false:330;true:0| + | 1,3 | abcda,abcda | depart,arrive | true:214,false:30 true:150 true:270,true:30 true:180 false:330;true:214| diff --git a/features/support/data_classes.js b/features/support/data_classes.js index 8eeaab336..391bb1c6d 100644 --- a/features/support/data_classes.js +++ b/features/support/data_classes.js @@ -52,24 +52,91 @@ module.exports = { match (got, want) { var matchPercent = want.match(/(.*)\s+~(.+)%$/), matchAbs = want.match(/(.*)\s+\+\-(.+)$/), - matchRe = want.match(/^\/(.*)\/$/); + matchRe = want.match(/^\/(.*)\/$/), + // we use this for matching before/after bearing + matchBearingListAbs = want.match(/^((\d+)->(\d+))(,(\d+)->(\d+))*\s+\+\-(.+)$/), + matchIntersectionListAbs = want.match(/^(((((true|false):\d+)\s{0,1})+,{0,1})+;{0,1})+\s+\+\-(.+)$/); + + function inRange(margin, got, want) { + var fromR = parseFloat(want) - margin, + toR = parseFloat(want) + margin; + return parseFloat(got) >= fromR && parseFloat(got) <= toR; + } + function parseIntersectionString(str) { + return str.split(';') + .map((turn_intersections) => turn_intersections + .split(',') + .map((intersection) => intersection + .split(' ') + .map((entry_bearing_pair) => entry_bearing_pair + .split(':')))); + } if (got === want) { return true; + } else if (matchBearingListAbs) { + let want_and_margin = want.split('+-'), + margin = parseFloat(want_and_margin[1].trim()), + want_pairs = want_and_margin[0].trim().split(',').map((pair) => pair.split('->')), + got_pairs = got.split(',').map((pair) => pair.split('->')); + if (want_pairs.length != got_pairs.length) + { + return false; + } + for (var i = 0; i < want_pairs.length; ++i) + { + if (!inRange(margin, got_pairs[i][0], want_pairs[i][0]) || + !inRange(margin, got_pairs[i][1], want_pairs[i][1])) + { + return false; + } + } + return true; + } else if (matchIntersectionListAbs) { + let margin = parseFloat(want.split('+-')[1]), + want_intersections = parseIntersectionString(want.split('+-')[0].trim()), + got_intersections = parseIntersectionString(got); + if (want_intersections.length != got_intersections.length) + { + return false; + } + for (let step_idx = 0; step_idx < want_intersections.length; ++step_idx) + { + if (want_intersections[step_idx].length != got_intersections[step_idx].length) + { + return false; + } + for (let intersection_idx = 0; intersection_idx < want_intersections[step_idx].length; ++intersection_idx) + { + if (want_intersections[step_idx][intersection_idx].length != got_intersections[step_idx][intersection_idx].length) + { + return false; + } + for (let pair_idx = 0; pair_idx < want_intersections[step_idx][intersection_idx].length; ++pair_idx) + { + let want_pair = want_intersections[step_idx][intersection_idx][pair_idx], + got_pair = got_intersections[step_idx][intersection_idx][pair_idx]; + if (got_pair[0] != want_pair[0] || + !inRange(margin, got_pair[1], want_pair[1])) + { + return false; + } + } + } + } + return true; } else if (matchPercent) { // percentage range: 100 ~ 5% var target = parseFloat(matchPercent[1]), percentage = parseFloat(matchPercent[2]); if (target === 0) { return true; } else { - var ratio = Math.abs(1 - parseFloat(got) / target); + let ratio = Math.abs(1 - parseFloat(got) / target); return 100 * ratio < percentage; } } else if (matchAbs) { // absolute range: 100 +-5 - var margin = parseFloat(matchAbs[2]), - fromR = parseFloat(matchAbs[1]) - margin, - toR = parseFloat(matchAbs[1]) + margin; - return parseFloat(got) >= fromR && parseFloat(got) <= toR; + let margin = parseFloat(matchAbs[2]); + return inRange(margin, got, matchAbs[1]); } else if (matchRe) { // regex: /a,b,.*/ return got.match(matchRe[1]); } else { diff --git a/features/testbot/bearing_param.feature b/features/testbot/bearing_param.feature index 523590738..267a39622 100644 --- a/features/testbot/bearing_param.feature +++ b/features/testbot/bearing_param.feature @@ -35,10 +35,10 @@ Feature: Bearing parameter When I route I should get | from | to | bearings | route | bearing | | 0 | c | 0 0 | | | - | 0 | c | 45 45 | bc,bc | 0->45,45->0| + | 0 | c | 45 45 | bc,bc | 0->44,44->0 +- 1| | 0 | c | 85 85 | | | | 0 | c | 95 95 | | | - | 0 | c | 135 135 | ac,ac | 0->136,136->0 | + | 0 | c | 135 135 | ac,ac | 0->135,135->0 +- 1| | 0 | c | 180 180 | | | Scenario: Testbot - Initial bearing on split way