diff --git a/modules/core/way.js b/modules/core/way.js index d9d1400fa..4574a66cf 100644 --- a/modules/core/way.js +++ b/modules/core/way.js @@ -127,28 +127,47 @@ _.extend(Way.prototype, { 'left', 'slight_left', 'sharp_left', 'through', 'right', 'slight_right', 'sharp_right', 'reverse', 'merge_to_left', 'merge_to_right', 'none' ]; - var parsedArray = parsePipeString(key, n); - if (!parsedArray) return; - - return parsedArray.map(function(l) { - return l.map(function(i) { - return validValues.indexOf(i) === -1 ? 'unknown': i; - }); - }); - } - - function parseMaxspeed(key, n) { var str = tags[key]; if (!str) return; - return str.split('|') - .filter(function(s, i) { - return i < n; - }) - .map(function(s) { - if (s === '') return 'none'; + var parsedArray = str.split('|') + .slice(0, n) + .map(function (s) { + if (s === '') s = 'none'; + return s.split(';') + .map(function (d) { + return validValues.indexOf(d) === -1 ? 'unknown': d; + }); + }); + while (parsedArray.length < n) { + parsedArray.push(['unknown']); + } + return parsedArray; + } + + function parseMaxspeed() { + var maxspeed = tags.maxspeed; + if (_.isNumber(maxspeed)) return maxspeed; + if (_.isString(maxspeed)) { + maxspeed = maxspeed.match(/^([0-9][\.0-9]+?)(?:[ ]?(?:km\/h|kmh|kph|mph|knots))?$/g); + if (!maxspeed) return; + return parseInt(maxspeed); + } + } + + function parseMaxspeedLanes(key, n) { + var str = tags[key]; + if (!str) return; + var parsedArray = str.split('|') + .slice(0, n) + .map(function (s) { var m = parseInt(s); + if (s === '' || m === maxspeed) return 'none'; return _.isNaN(m) ? 'unknown': m; }); + while (parsedArray.length < n) { + parsedArray.push('unknown'); + } + return parsedArray; } function parseLaneDirections() { @@ -242,11 +261,13 @@ _.extend(Way.prototype, { var turnLanesForward = parseTurnLanes('turn:lanes:forward', forward); var turnLanesBackward = parseTurnLanes('turn:lanes:backward', backward); - var maxspeedLanes = parseMaxspeed('maxspeed:lanes', laneCount); - var maxspeedLanesForward = parseMaxspeed('maxspeed:lanes:forward', forward); - var maxspeedLanesBackward = parseMaxspeed('maxspeed:lanes:backward', backward); + var maxspeed = parseMaxspeed(); + var maxspeedLanes = parseMaxspeedLanes('maxspeed:lanes', laneCount); + var maxspeedLanesForward = parseMaxspeedLanes('maxspeed:lanes:forward', forward); + var maxspeedLanesBackward = parseMaxspeedLanes('maxspeed:lanes:backward', backward); - // fill each undefined lanesArray's direction element with 'forward/bothwats/backward'. + + // fill each undefined lanesArray's direction element with 'forward/bothways/backward'. smartFill(lanesArray, 'direction', _.fill(Array(forward), 'forward')); smartFill(lanesArray, 'direction', _.fill(Array(bothways), 'bothways')); smartFill(lanesArray, 'direction', _.fill(Array(backward), 'backward')); @@ -283,6 +304,7 @@ _.extend(Way.prototype, { turnLanes: turnLanes, turnLanesForward: turnLanesForward, turnLanesBackward: turnLanesBackward, + maxspeed: maxspeed, maxspeedLanes: maxspeedLanes, maxspeedLanesForward: maxspeedLanesForward, maxspeedLanesBackward: maxspeedLanesBackward, diff --git a/test/spec/core/way.js b/test/spec/core/way.js index 536ad9568..b688e8049 100644 --- a/test/spec/core/way.js +++ b/test/spec/core/way.js @@ -1106,7 +1106,7 @@ describe('iD.Way', function() { expect(metadata.turnLanes) .to.deep.equal([ - ['slight_left'], ['none'], ['none'], ['none'], ['none'] + ['slight_left'], ['unknown'], ['unknown'], ['unknown'], ['unknown'] ]); }); @@ -1124,11 +1124,11 @@ describe('iD.Way', function() { expect(metadata.turnLanesForward) .to.deep.equal([ - ['slight_left'], ['none'], ['none'] + ['slight_left'], ['unknown'], ['unknown'] ]); expect(metadata.turnLanesBackward) .to.deep.equal([ - ['through'], ['none'] + ['through'], ['unknown'] ]); }); @@ -1224,8 +1224,6 @@ describe('iD.Way', function() { }); - - it('parses correctly when turn:lanes= ||x', function() { var metadata = iD.Way({ tags: { @@ -1250,7 +1248,7 @@ describe('iD.Way', function() { }).lanes().metadata; expect(metadata.turnLanes) - .to.deep.equal([['none'], ['through'], ['none'], ['none'], ['none']]); + .to.deep.equal([['none'], ['through'], ['none'], ['unknown'], ['unknown']]); }); it('parses correctly when turn:lanes:forward= ||x', function() { @@ -1311,8 +1309,99 @@ describe('iD.Way', function() { }); - describe.only('maxspeed', function() { - it('should parse maxspeed correctly', function() { + describe('maxspeed', function() { + it('should parse maxspeed without any units correctly', function() { + var maxspeed = iD.Way({ + tags: { + highway: 'residential', + lanes: 5, + 'maxspeed': '70' + } + }).lanes().metadata.maxspeed; + expect(maxspeed).to.equal(70); + }); + it('should parse maxspeed with km/h correctly', function() { + var maxspeed = iD.Way({ + tags: { + highway: 'residential', + lanes: 5, + 'maxspeed': '70 km/h' + } + }).lanes().metadata.maxspeed; + expect(maxspeed).to.equal(70); + }); + it('should parse maxspeed with kmh correctly', function() { + var maxspeed = iD.Way({ + tags: { + highway: 'residential', + lanes: 5, + 'maxspeed': '70kmh' + } + }).lanes().metadata.maxspeed; + expect(maxspeed).to.equal(70); + }); + it('should parse maxspeed with kph correctly', function() { + var maxspeed = iD.Way({ + tags: { + highway: 'residential', + lanes: 5, + 'maxspeed': '70 kph' + } + }).lanes().metadata.maxspeed; + expect(maxspeed).to.equal(70); + }); + it('should parse maxspeed with mph correctly', function() { + var maxspeed = iD.Way({ + tags: { + highway: 'residential', + lanes: 5, + 'maxspeed': '70mph' + } + }).lanes().metadata.maxspeed; + expect(maxspeed).to.equal(70); + }); + it('should parse maxspeed with knots correctly', function() { + var maxspeed = iD.Way({ + tags: { + highway: 'residential', + lanes: 5, + 'maxspeed': '50knots' + } + }).lanes().metadata.maxspeed; + expect(maxspeed).to.equal(50); + }); + it('should return undefined when incorrect maxspeed unit provided ', function() { + var maxspeed = iD.Way({ + tags: { + highway: 'residential', + lanes: 5, + 'maxspeed': '70km' + } + }).lanes().metadata.maxspeed; + expect(maxspeed).to.equal(undefined); + }); + it('should return undefined when incorrect maxspeed value provided ', function() { + var maxspeed = iD.Way({ + tags: { + highway: 'residential', + lanes: 5, + 'maxspeed': 'a70knots' + } + }).lanes().metadata.maxspeed; + expect(maxspeed).to.equal(undefined); + }); + it('should return undefined when maxspeed not provided ', function() { + var maxspeed = iD.Way({ + tags: { + highway: 'residential', + lanes: 5, + } + }).lanes().metadata.maxspeed; + expect(maxspeed).to.equal(undefined); + }); + }); + describe('maxspeed:lanes', function() { + it('should parse correctly', function() { var maxspeedLanes = iD.Way({ tags: { highway: 'residential', @@ -1320,11 +1409,145 @@ describe('iD.Way', function() { 'maxspeed:lanes': '30|40|40|40|40' } }).lanes().metadata.maxspeedLanes; - expect(maxspeedLanes).to.deep.equal([ 30, 40, 40, 40, 40 ]); + }); + it('should parse maxspeed:lanes:forward/backward correctly', function() { + var metadata = iD.Way({ + tags: { + highway: 'residential', + lanes: 5, + maxspeed: 30, + 'lanes:forward': 4, + 'lanes:backward': 1, + 'maxspeed:lanes:forward': '30|40|40|40', + 'maxspeed:lanes:backward': '30' + } + }).lanes().metadata; + expect(metadata.maxspeedLanesForward).to.deep.equal([ + 'none', 40, 40, 40 + ]); + expect(metadata.maxspeedLanesBackward).to.deep.equal([ + 'none' + ]); + }); + + it('should parse correctly when some values maxspeed:lanes are implied by x||y notation', function() { + var maxspeedLanes = iD.Way({ + tags: { + highway: 'residential', + lanes: 4, + maxspeed: '40kmh', + 'maxspeed:lanes': '30|||40' + } + }).lanes().metadata.maxspeedLanes; + expect(maxspeedLanes).to.deep.equal([ + 30, 'none', 'none', 'none' + ]); + }); + + it('should parse correctly when some values maxspeed:lanes are implied by x||| notation', function() { + var maxspeedLanes = iD.Way({ + tags: { + highway: 'residential', + lanes: 4, + maxspeed: '60kmh', + 'maxspeed:lanes': '30|||' + } + }).lanes().metadata.maxspeedLanes; + expect(maxspeedLanes).to.deep.equal([ + 30, 'none', 'none', 'none' + ]); + }); + + it('should return none for each maxspeed:lanes which equals maxspeed', function() { + var maxspeedLanes = iD.Way({ + tags: { + highway: 'residential', + lanes: 5, + maxspeed: '40kmh', + 'maxspeed:lanes': '30|40|40|40|40' + } + }).lanes().metadata.maxspeedLanes; + expect(maxspeedLanes).to.deep.equal([ + 30, 'none', 'none', 'none', 'none' + ]); + maxspeedLanes = iD.Way({ + tags: { + highway: 'residential', + lanes: 5, + maxspeed: '50kmh', + 'maxspeed:lanes': '30|40|40|40|40' + } + }).lanes().metadata.maxspeedLanes; + expect(maxspeedLanes).to.deep.equal([ + 30, 40, 40, 40, 40 + ]); + maxspeedLanes = iD.Way({ + tags: { + highway: 'residential', + lanes: 5, + maxspeed: '30knots', + 'maxspeed:lanes': '30|40|40|40|40' + } + }).lanes().metadata.maxspeedLanes; + expect(maxspeedLanes).to.deep.equal([ + 'none', 40, 40, 40, 40 + ]); + }); + it('should return \'unknown\' for every bogus maxspeed:lane value', function() { + var maxspeedLanes = iD.Way({ + tags: { + highway: 'residential', + lanes: 5, + maxspeed: '30kmh', + 'maxspeed:lanes': '30|40|fourty|40|40' + } + }).lanes().metadata.maxspeedLanes; + expect(maxspeedLanes).to.deep.equal([ + 'none', 40, 'unknown', 40, 40 + ]); + maxspeedLanes = iD.Way({ + tags: { + highway: 'residential', + lanes: 5, + maxspeed: '30kmh', + 'maxspeed:lanes': '30|40|fourty|40|random' + } + }).lanes().metadata.maxspeedLanes; + expect(maxspeedLanes).to.deep.equal([ + 'none', 40, 'unknown', 40, 'unknown' + ]); + }); + + it('should return \'unknown\' when maxspeed:lanes length is less than lane count', function() { + var maxspeedLanes = iD.Way({ + tags: { + highway: 'primary', + lanes: 4, + maxspeed: '40mph', + 'maxspeed:lanes': '40|60|60' + } + }).lanes().metadata.maxspeedLanes; + expect(maxspeedLanes).to.deep.equal([ + 'none', 60, 60, 'unknown' + ]); + }); + + it('should clip if maxspeed:lanes length is more than lane count', function() { + var maxspeedLanes = iD.Way({ + tags: { + highway: 'primary', + lanes: 4, + maxspeed: '40mph', + 'maxspeed:lanes': '40|60|60|60|40' + } + }).lanes().metadata.maxspeedLanes; + expect(maxspeedLanes).to.deep.equal([ + 'none', 60, 60, 60 + ]); }); }); });