From fab6dfa3dd848c8e7a635f38f40750be1773c268 Mon Sep 17 00:00:00 2001 From: Thomas Petillon Date: Sat, 11 Apr 2020 16:26:17 +0200 Subject: [PATCH] Add the `utilCompareIDs()` function --- modules/util/index.js | 1 + modules/util/util.js | 56 ++++++++++++++++++++---------------------- test/spec/util/util.js | 32 ++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 29 deletions(-) diff --git a/modules/util/index.js b/modules/util/index.js index 26fb02c79..a1fd6c74f 100644 --- a/modules/util/index.js +++ b/modules/util/index.js @@ -35,6 +35,7 @@ export { utilHighlightEntities } from './util'; export { utilKeybinding } from './keybinding'; export { utilNoAuto } from './util'; export { utilObjectOmit } from './object'; +export { utilCompareIDs } from './util'; export { utilOldestID } from './util'; export { utilPrefixCSSProperty } from './util'; export { utilPrefixDOMProperty } from './util'; diff --git a/modules/util/util.js b/modules/util/util.js index ec3d5d539..f80128b61 100644 --- a/modules/util/util.js +++ b/modules/util/util.js @@ -582,6 +582,29 @@ export function utilUnicodeCharsTruncated(str, limit) { return Array.from(str).slice(0, limit).join(''); } +function toNumericID(id) { + var match = id.match(/^[cnwr](-?\d+)$/); + if (match) { + return parseInt(match[1], 10); + } + return NaN; +} + +function compareNumericIDs(left, right) { + if (isNaN(left) && isNaN(right)) return -1; + if (isNaN(left)) return 1; + if (isNaN(right)) return -1; + if (Math.sign(left) !== Math.sign(right)) return -Math.sign(left); + if (Math.sign(left) < 0) return Math.sign(right - left); + return Math.sign(left - right); +} + +// Returns -1 if the first parameter ID is older than the second, +// 1 if the second parameter is older, 0 if they are the same. +// If both IDs are test IDs, the function returns -1. +export function utilCompareIDs(left, right) { + return compareNumericIDs(toNumericID(left), toNumericID(right)); +} // Returns the chronologically oldest ID in the list. // Database IDs (with positive numbers) before editor ones (with negative numbers). @@ -592,40 +615,15 @@ export function utilOldestID(ids) { return undefined; } - var idPattern = /^[cnwr](-?)(\d+)$/; - var decomposeID = (id) => { - var res = { - id: id, - num: NaN - }; - - var match = id.match(idPattern); - if (match) { - res.num = parseInt(match[2], 10); - res.isNew = !!match[1]; - } - - return res; - }; - - var compareDecomposed = (left, right) => { - if (isNaN(left.num) && isNaN(right.num)) return -1; - if (isNaN(left.num)) return 1; - if (isNaN(right.num)) return -1; - if (left.isNew && !right.isNew) return 1; - if (!left.isNew && right.isNew) return -1; - return Math.sign(left.num - right.num); - }; - var oldestIDIndex = 0; - var oldestID = decomposeID(ids[0]); + var oldestID = toNumericID(ids[0]); for (var i = 1; i < ids.length; i++) { - var decomposed = decomposeID(ids[i]); + var num = toNumericID(ids[i]); - if (compareDecomposed(oldestID, decomposed) === 1) { + if (compareNumericIDs(oldestID, num) === 1) { oldestIDIndex = i; - oldestID = decomposed; + oldestID = num; } } diff --git a/test/spec/util/util.js b/test/spec/util/util.js index 9768bfa12..a033afc38 100644 --- a/test/spec/util/util.js +++ b/test/spec/util/util.js @@ -226,6 +226,38 @@ describe('iD.util', function() { }); }); + describe('utilCompareIDs', function() { + it('sorts existing IDs numerically in ascending order', function() { + expect(iD.utilCompareIDs('w100', 'w200')).to.eql(-1); + expect(iD.utilCompareIDs('w100', 'w50')).to.eql(1); + expect(iD.utilCompareIDs('w100', 'w100')).to.eql(0); + }); + it('sorts new IDs numerically in descending order', function() { + expect(iD.utilCompareIDs('w-100', 'w-200')).to.eql(-1); + expect(iD.utilCompareIDs('w-100', 'w-50')).to.eql(1); + expect(iD.utilCompareIDs('w-100', 'w-100')).to.eql(0); + }); + it('sorts existing IDs before new IDs', function() { + expect(iD.utilCompareIDs('w-1', 'w1')).to.eql(1); + expect(iD.utilCompareIDs('w1', 'w-1')).to.eql(-1); + expect(iD.utilCompareIDs('w-100', 'w1')).to.eql(1); + expect(iD.utilCompareIDs('w100', 'w-1')).to.eql(-1); + expect(iD.utilCompareIDs('w-1', 'w100')).to.eql(1); + expect(iD.utilCompareIDs('w1', 'w-100')).to.eql(-1); + }); + it('sorts existing and new IDs before anything else', function() { + expect(iD.utilCompareIDs('w1', 'asdf')).to.eql(-1); + expect(iD.utilCompareIDs('asdf', 'w1')).to.eql(1); + expect(iD.utilCompareIDs('w-1', 'asdf')).to.eql(-1); + expect(iD.utilCompareIDs('asdf', 'w-1')).to.eql(1); + }); + it('returns -1 for other strings', function() { + expect(iD.utilCompareIDs('aaa', 'b')).to.eql(-1); + expect(iD.utilCompareIDs('b', 'aaa')).to.eql(-1); + expect(iD.utilCompareIDs('a', 'a')).to.eql(-1); + }); + }); + describe('utilDisplayName', function() { it('returns the name if tagged with a name', function() { expect(iD.utilDisplayName({tags: {name: 'East Coast Greenway'}})).to.eql('East Coast Greenway');