diff --git a/src/__tests__/scales/yds.ts b/src/__tests__/scales/yds.ts index fef8564..3883f09 100644 --- a/src/__tests__/scales/yds.ts +++ b/src/__tests__/scales/yds.ts @@ -70,6 +70,15 @@ describe('YosemiteDecimal', () => { test('grade with slash', () => { expect(YosemiteDecimal.isType('5.10a/b')).toBeTruthy() }) + test.failing('grade with slash', () => { + expect(YosemiteDecimal.isType('5.10d/5.11a')).toBeTruthy() + }) + + test.failing('grade with non-consecutive slash grades', () => { + expect(YosemiteDecimal.isType('5.10d/c')).toBeFalsy() + expect(YosemiteDecimal.isType('5.10a/c')).toBeFalsy() + expect(YosemiteDecimal.isType('5.10c/5.11a')).toBeFalsy() + }) test('incorrect type', () => { expect(YosemiteDecimal.isType('11+')).toBeFalsy() @@ -112,4 +121,17 @@ describe('YosemiteDecimal', () => { expect(YosemiteDecimal.getGradeBand('5.15a')).toEqual(GradeBands.EXPERT) }) }) + + describe('Slash scores', () => { + test('scores of slash grades should be subset of neighboring scores', () => { + const slashScore = YosemiteDecimal.getScore('5.10a/b') + const lowScore = YosemiteDecimal.getScore('5.10a') + const highScore = YosemiteDecimal.getScore('5.10b') + + expect(slashScore[0]).toBeGreaterThan(lowScore[0]) + expect(slashScore[1]).toBeGreaterThan(lowScore[1]) + expect(slashScore[0]).toBeLessThan(highScore[0]) + expect(slashScore[1]).toBeLessThan(highScore[1]) + }) + }) }) diff --git a/src/scales/yds.ts b/src/scales/yds.ts index 73395dc..fc21f8e 100644 --- a/src/scales/yds.ts +++ b/src/scales/yds.ts @@ -66,13 +66,16 @@ const getScore = (grade: string): number | Tuple => { } const [wholeMatch, basicGrade, number, letter, plusOrMinusOrSlash] = parse let normalizedGrade = basicGrade - const plusSlash = ['+', '/'].includes(plusOrMinusOrSlash) + + const slash = plusOrMinusOrSlash?.startsWith('/') const minus = plusOrMinusOrSlash === '-' + const plus = plusOrMinusOrSlash === '+' + let normalizedLetter = letter const isLargeNonLetter = parseInt(number, 10) > 9 && normalizedLetter === '' if (isLargeNonLetter) { // 11-, 13+, 12 - normalizedLetter = minus ? 'a' : plusSlash ? 'c' : 'b' + normalizedLetter = minus ? 'a' : (plus || slash) ? 'c' : 'b' } normalizedGrade = basicGrade + normalizedLetter const basicScore = findScoreRange((r: Route) => { @@ -80,18 +83,18 @@ const getScore = (grade: string): number | Tuple => { }, routes) if (wholeMatch !== normalizedGrade) { - let otherGrade - // 5.11+, 5.10a/b - if (plusSlash || isLargeNonLetter) { - otherGrade = (typeof basicScore === 'number' ? basicScore : basicScore[1]) + 1 + let otherScore + if (plus || slash || isLargeNonLetter) { + // 5.11+, 5.10a/b + otherScore = (typeof basicScore === 'number' ? basicScore : basicScore[1]) + 1 } else if (minus) { // 5.11- - otherGrade = (typeof basicScore === 'number' ? basicScore : basicScore[0]) - 1 + otherScore = (typeof basicScore === 'number' ? basicScore : basicScore[0]) - 1 } - if (otherGrade !== undefined) { + if (otherScore !== undefined) { const nextGrade = findScoreRange((r: Route) => { - return r.yds.toLowerCase() === routes[Math.max(otherGrade, 0)].yds.toLowerCase() + return r.yds.toLowerCase() === routes[Math.max(otherScore, 0)].yds.toLowerCase() }, routes) return [getAvgScore(basicScore), getAvgScore(nextGrade)].sort((a, b) => a - b) as Tuple }