Skip to content
Open
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
3 changes: 2 additions & 1 deletion src/GradeParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ export const convertGrade = (
return ''
}
const sameConversionGroup: boolean = fromScale.conversionGroup === toScale.conversionGroup
if (!sameConversionGroup) {
const isResearchConversion: boolean = fromScale.conversionGroup === 'research' || toScale.conversionGroup === 'research'
if (!sameConversionGroup && !isResearchConversion) {
console.warn(
`Scale: ${fromScale.displayName} doesn't support converting to Scale: ${toScale.displayName}`
)
Expand Down
6 changes: 4 additions & 2 deletions src/GradeScale.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ export const GradeScales = {
EWBANK: 'ewbank',
SAXON: 'saxon',
NORWEGIAN: 'norwegian',
BRAZILIAN_CRUX: 'brazilian_crux'
BRAZILIAN_CRUX: 'brazilian_crux',
IRCRA: 'ircra'
} as const

export type GradeScalesTypes = typeof GradeScales[keyof typeof GradeScales]
Expand All @@ -35,7 +36,8 @@ export const ConversionGroups = {
AID: 'aid',
FREE: 'free',
BOULDERING: 'bouldering',
ICE: 'ice'
ICE: 'ice',
RESEARCH: 'research'
} as const

export type ConversionGroupsTypes = typeof ConversionGroups[keyof typeof ConversionGroups]
Expand Down
51 changes: 50 additions & 1 deletion src/__tests__/GradeParser.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { getScoreForSort, convertGrade, getScale } from '../GradeParser'
import { GradeScales } from '../GradeScale'
import { VScale, Font, YosemiteDecimal, French, Saxon, AI, WI } from '../scales'
import { VScale, Font, YosemiteDecimal, French, Saxon, AI, WI, IRCRA } from '../scales'

describe('Grade Scales', () => {
beforeAll(() => {
Expand Down Expand Up @@ -322,4 +322,53 @@ describe('Grade Scales', () => {
)
})
})

describe('IRCRA', () => {
test('32 > 1', () => {
expect(getScoreForSort('32', GradeScales.IRCRA)).toBeGreaterThan(
getScoreForSort('1', GradeScales.IRCRA)
)
})

test('15 > 10', () => {
expect(getScoreForSort('15', GradeScales.IRCRA)).toBeGreaterThan(
getScoreForSort('10', GradeScales.IRCRA)
)
})

test('25 > 20', () => {
expect(getScoreForSort('25', GradeScales.IRCRA)).toBeGreaterThan(
getScoreForSort('20', GradeScales.IRCRA)
)
})

test('returns a GradeScale given the name', () => {
expect(getScale(GradeScales.IRCRA)).toEqual(IRCRA)
})

test('convert IRCRA to FONT', () => {
expect(convertGrade('14', GradeScales.IRCRA, GradeScales.FONT)).toEqual('5b+/5c')
})

test('convert IRCRA to VSCALE', () => {
expect(convertGrade('14', GradeScales.IRCRA, GradeScales.VSCALE)).toEqual('V2')
})

test('convert IRCRA to YDS', () => {
expect(convertGrade('15', GradeScales.IRCRA, GradeScales.YDS)).toEqual('5.10a')
})

test('convert IRCRA to French', () => {
expect(convertGrade('15', GradeScales.IRCRA, GradeScales.FRENCH)).toEqual('5c+/6a')
})

// Test reverse conversions
test('convert FONT to IRCRA', () => {
expect(convertGrade('6a', GradeScales.FONT, GradeScales.IRCRA)).toEqual('15/16')
})

test('convert VSCALE to IRCRA', () => {
expect(convertGrade('V2', GradeScales.VSCALE, GradeScales.IRCRA)).toEqual('13/14')
})
})
})
106 changes: 106 additions & 0 deletions src/__tests__/scales/ircra.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { GradeBands } from '../../GradeBands'
import { IRCRA } from '../../scales'

describe('IRCRA', () => {
describe('Get Score', () => {
test('32 > 1', () => {
const lowGrade = IRCRA.getScore('1')
const highGrade = IRCRA.getScore('32')
expect(highGrade[0]).toBeGreaterThan(lowGrade[1])
})

test('15 > 10', () => {
const highGrade = IRCRA.getScore('15')
const lowGrade = IRCRA.getScore('10')
expect(highGrade[0]).toBeGreaterThan(lowGrade[1])
})

test('25 > 20', () => {
const highGrade = IRCRA.getScore('25')
const lowGrade = IRCRA.getScore('20')
expect(highGrade[0]).toBeGreaterThan(lowGrade[1])
})
})

describe('invalid grade format', () => {
jest.spyOn(console, 'warn').mockImplementation()
beforeEach(() => {
jest.clearAllMocks()
})
test('invalid grade with letters', () => {
const invalidGrade = IRCRA.getScore('5a')
expect(console.warn).toHaveBeenCalledWith('Unexpected grade format: 5a for grade scale IRCRA')
expect(invalidGrade).toEqual(-1)
})
test('invalid grade with decimal', () => {
const invalidGrade = IRCRA.getScore('15.5')
expect(console.warn).toHaveBeenCalledWith('Unexpected grade format: 15.5 for grade scale IRCRA')
expect(invalidGrade).toEqual(-1)
})
test('invalid grade with plus', () => {
const invalidGrade = IRCRA.getScore('15+')
expect(console.warn).toHaveBeenCalledWith('Unexpected grade format: 15+ for grade scale IRCRA')
expect(invalidGrade).toEqual(-1)
})
test('invalid grade with minus', () => {
const invalidGrade = IRCRA.getScore('15-')
expect(console.warn).toHaveBeenCalledWith('Unexpected grade format: 15- for grade scale IRCRA')
expect(invalidGrade).toEqual(-1)
})
test('invalid grade with slash', () => {
const invalidGrade = IRCRA.getScore('15/16')
expect(console.warn).toHaveBeenCalledWith('Unexpected grade format: 15/16 for grade scale IRCRA')
expect(invalidGrade).toEqual(-1)
})
test('not IRCRA scale', () => {
const invalidGrade = IRCRA.getScore('v11')
expect(console.warn).toHaveBeenCalledWith('Unexpected grade format: v11 for grade scale IRCRA')
expect(invalidGrade).toEqual(-1)
})
})

describe('Get Grade', () => {
test('bottom of range', () => {
expect(IRCRA.getGrade(0)).toBe('1')
})

test('top of range', () => {
expect(IRCRA.getGrade(1000)).toBe('32')
})

test('single score provided', () => {
expect(IRCRA.getGrade(34)).toBe('9')
expect(IRCRA.getGrade(34.5)).toBe('9')
expect(IRCRA.getGrade(35)).toBe('9')
})
test('range of scores provided', () => {
expect(IRCRA.getGrade([0.5, 2])).toBe('1')
expect(IRCRA.getGrade([8, 12])).toBe('2/4')
expect(IRCRA.getGrade([16, 17])).toBe('5')
})
})

describe('Get Grade Band', () => {
test('gets Gradeband', () => {
expect(IRCRA.getGradeBand('1')).toEqual(GradeBands.BEGINNER)
expect(IRCRA.getGradeBand('32')).toEqual(GradeBands.EXPERT)
})
})

describe('Is Type', () => {
test('valid IRCRA grades', () => {
expect(IRCRA.isType('1')).toBe(true)
expect(IRCRA.isType('15')).toBe(true)
expect(IRCRA.isType('32')).toBe(true)
})

test('invalid IRCRA grades', () => {
expect(IRCRA.isType('5a')).toBe(false)
expect(IRCRA.isType('15.5')).toBe(false)
expect(IRCRA.isType('15+')).toBe(false)
expect(IRCRA.isType('15-')).toBe(false)
expect(IRCRA.isType('15/16')).toBe(false)
expect(IRCRA.isType('v11')).toBe(false)
})
})
})
4 changes: 4 additions & 0 deletions src/data/csvtojson.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,7 @@ export const ICE_GRADE_TABLE: Promise<IceGrade[]> = getData(CSV_PATH_ICE, JSON_P
const CSV_PATH_AID = path.join(dataDir, 'aid.csv')
const JSON_PATH_AID = path.join(dataDir, 'aid.json')
export const AID_GRADE_TABLE: Promise<AidGrade[]> = getData(CSV_PATH_AID, JSON_PATH_AID)

const CSV_PATH_RESEARCH = path.join(dataDir, 'research.csv')
const JSON_PATH_RESEARCH = path.join(dataDir, 'research.json')
export const RESEARCH_GRADE_TABLE: Promise<any[]> = getData(CSV_PATH_RESEARCH, JSON_PATH_RESEARCH)
109 changes: 109 additions & 0 deletions src/data/research.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
score,ircra
0,1
1,1
2,1
3,1
4,1
5,1
6,2
7,2
8,2
9,3
10,3
11,3
12,4
13,4
14,4
15,5
16,5
17,5
18,6
19,6
20,6
21,7
22,7
23,7
24,8
25,8
26,8
27,9
28,9
29,9
30,9
31,9
32,9
33,9
34,9
35,9
36,10
37,10
38,10
39,10
40,10
41,11
42,11
43,11
44,11
45,11
46,12
47,12
48,12
49,12
50,12
51,13
52,13
53,13
54,13
55,14
56,14
57,14
58,15
59,15
60,15
61,16
62,16
63,16
64,17
65,17
66,17
67,18
68,18
69,18
70,19
71,19
72,20
73,20
74,20
75,21
76,21
77,21
78,22
79,22
80,23
81,23
82,23
83,24
84,24
85,25
86,25
87,25
88,26
89,26
90,27
91,27
92,28
93,28
94,29
95,29
96,30
97,30
98,31
99,31
100,32
101,32
102,32
103,32
104,32
105,32
106,32
107,32
1 change: 1 addition & 0 deletions src/data/research.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{"score":0,"ircra":"1"},{"score":1,"ircra":"1"},{"score":2,"ircra":"1"},{"score":3,"ircra":"1"},{"score":4,"ircra":"1"},{"score":5,"ircra":"1"},{"score":6,"ircra":"2"},{"score":7,"ircra":"2"},{"score":8,"ircra":"2"},{"score":9,"ircra":"3"},{"score":10,"ircra":"3"},{"score":11,"ircra":"3"},{"score":12,"ircra":"4"},{"score":13,"ircra":"4"},{"score":14,"ircra":"4"},{"score":15,"ircra":"5"},{"score":16,"ircra":"5"},{"score":17,"ircra":"5"},{"score":18,"ircra":"6"},{"score":19,"ircra":"6"},{"score":20,"ircra":"6"},{"score":21,"ircra":"7"},{"score":22,"ircra":"7"},{"score":23,"ircra":"7"},{"score":24,"ircra":"8"},{"score":25,"ircra":"8"},{"score":26,"ircra":"8"},{"score":27,"ircra":"9"},{"score":28,"ircra":"9"},{"score":29,"ircra":"9"},{"score":30,"ircra":"9"},{"score":31,"ircra":"9"},{"score":32,"ircra":"9"},{"score":33,"ircra":"9"},{"score":34,"ircra":"9"},{"score":35,"ircra":"9"},{"score":36,"ircra":"10"},{"score":37,"ircra":"10"},{"score":38,"ircra":"10"},{"score":39,"ircra":"10"},{"score":40,"ircra":"10"},{"score":41,"ircra":"11"},{"score":42,"ircra":"11"},{"score":43,"ircra":"11"},{"score":44,"ircra":"11"},{"score":45,"ircra":"11"},{"score":46,"ircra":"12"},{"score":47,"ircra":"12"},{"score":48,"ircra":"12"},{"score":49,"ircra":"12"},{"score":50,"ircra":"12"},{"score":51,"ircra":"13"},{"score":52,"ircra":"13"},{"score":53,"ircra":"13"},{"score":54,"ircra":"13"},{"score":55,"ircra":"14"},{"score":56,"ircra":"14"},{"score":57,"ircra":"14"},{"score":58,"ircra":"15"},{"score":59,"ircra":"15"},{"score":60,"ircra":"15"},{"score":61,"ircra":"16"},{"score":62,"ircra":"16"},{"score":63,"ircra":"16"},{"score":64,"ircra":"17"},{"score":65,"ircra":"17"},{"score":66,"ircra":"17"},{"score":67,"ircra":"18"},{"score":68,"ircra":"18"},{"score":69,"ircra":"18"},{"score":70,"ircra":"19"},{"score":71,"ircra":"19"},{"score":72,"ircra":"20"},{"score":73,"ircra":"20"},{"score":74,"ircra":"20"},{"score":75,"ircra":"21"},{"score":76,"ircra":"21"},{"score":77,"ircra":"21"},{"score":78,"ircra":"22"},{"score":79,"ircra":"22"},{"score":80,"ircra":"23"},{"score":81,"ircra":"23"},{"score":82,"ircra":"23"},{"score":83,"ircra":"24"},{"score":84,"ircra":"24"},{"score":85,"ircra":"25"},{"score":86,"ircra":"25"},{"score":87,"ircra":"25"},{"score":88,"ircra":"26"},{"score":89,"ircra":"26"},{"score":90,"ircra":"27"},{"score":91,"ircra":"27"},{"score":92,"ircra":"28"},{"score":93,"ircra":"28"},{"score":94,"ircra":"29"},{"score":95,"ircra":"29"},{"score":96,"ircra":"30"},{"score":97,"ircra":"30"},{"score":98,"ircra":"31"},{"score":99,"ircra":"31"},{"score":100,"ircra":"32"},{"score":101,"ircra":"32"},{"score":102,"ircra":"32"},{"score":103,"ircra":"32"},{"score":104,"ircra":"32"},{"score":105,"ircra":"32"},{"score":106,"ircra":"32"},{"score":107,"ircra":"32"}]
6 changes: 4 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ import {
VScale,
WI,
YosemiteDecimal,
BrazilianCrux
BrazilianCrux,
IRCRA
} from './scales'

// Free Climbing Grades
Expand Down Expand Up @@ -347,5 +348,6 @@ export {
VScale,
WI,
YosemiteDecimal,
BrazilianCrux
BrazilianCrux,
IRCRA
}
11 changes: 9 additions & 2 deletions src/scales/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ import Aid from './aid'
import WI from './wi'
import BrazilianCrux from './brazilian'
import UIAA from './uiaa'
import IRCRA from './ircra'
import GradeScale, { GradeScales } from '../GradeScale'
export { Aid, VScale, Font, YosemiteDecimal, French, Saxon, UIAA, Ewbank, AI, WI, Norwegian, BrazilianCrux }
export { Aid, VScale, Font, YosemiteDecimal, French, Saxon, UIAA, Ewbank, AI, WI, Norwegian, BrazilianCrux, IRCRA }

export interface Boulder {
score: number
Expand Down Expand Up @@ -41,6 +42,11 @@ export interface AidGrade {
aid: string
}

export interface ResearchGrade {
score: number
ircra: string
}

export const scales: Record<
typeof GradeScales[keyof typeof GradeScales],
GradeScale | null
Expand All @@ -56,5 +62,6 @@ GradeScale | null
[GradeScales.BRAZILIAN_CRUX]: BrazilianCrux,
[GradeScales.AI]: AI,
[GradeScales.WI]: WI,
[GradeScales.AID]: Aid
[GradeScales.AID]: Aid,
[GradeScales.IRCRA]: IRCRA
}
Loading