From e7e54741d27eb863110c92e029b336182be8e6bd Mon Sep 17 00:00:00 2001 From: NotJayden Date: Mon, 7 Jun 2021 14:50:21 +0800 Subject: [PATCH 1/8] add conditional bosses filter if gamemode is seasonal --- package.json | 2 +- src/hiscores.ts | 10 ++++++---- tsconfig.json | 7 ++++++- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 6784221..0a9fb3b 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "osrs-json-hiscores", "version": "2.5.0", "description": "The Old School Runescape API wrapper that does more!", - "main": "lib/index.js", + "main": "lib/index", "types": "lib/index.d.ts", "files": [ "lib/**/*" diff --git a/src/hiscores.ts b/src/hiscores.ts index 2b3ce0d..b1c48a8 100644 --- a/src/hiscores.ts +++ b/src/hiscores.ts @@ -68,7 +68,7 @@ export async function getRSNFormat(rsn: string): Promise { * @param csv Raw CSV from the official OSRS API. * @returns Parsed stats object. */ -export function parseStats(csv: string): Stats { +export function parseStats(csv: string, mode: Gamemode = 'main'): Stats { const splitCSV = csv .split('\n') .filter((entry) => !!entry) @@ -97,11 +97,13 @@ export function parseStats(csv: string): Stats { return activity; }); + const filteredBosses = mode === 'seasonal'? BOSSES.filter((boss) => boss !== 'tempoross') : BOSSES; + const [leaguePoints] = activityObjects.splice(0, 1); const bhObjects = activityObjects.splice(0, BH_MODES.length); const clueObjects = activityObjects.splice(0, CLUES.length); const [lastManStanding, soulWarsZeal] = activityObjects.splice(0, 2); - const bossObjects = activityObjects.splice(0, BOSSES.length); + const bossObjects = activityObjects.splice(0, filteredBosses.length); const skills: Skills = skillObjects.reduce((prev, curr, index) => { const newSkills = { ...prev }; @@ -123,7 +125,7 @@ export function parseStats(csv: string): Stats { const bosses: Bosses = bossObjects.reduce((prev, curr, index) => { const newBosses = { ...prev }; - newBosses[BOSSES[index]] = curr; + newBosses[filteredBosses[index]] = curr; return newBosses; }, {} as Bosses); @@ -250,7 +252,7 @@ export async function getStatsByGamemode( if (response.status !== 200) { throw Error('Player not found'); } - const stats = parseStats(response.data); + const stats = parseStats(response.data, mode); return stats; } diff --git a/tsconfig.json b/tsconfig.json index ca4bf6a..cf7f094 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,7 +4,12 @@ "module": "commonjs", "declaration": true, "outDir": "./lib", - "strict": true + "strict": true, + "lib": ["ES2015", "DOM", "DOM.Iterable"], + "typeRoots": [ + "./node_modules/@types", + "./src/@types" + ] }, "include": ["src"], "exclude": ["node_modules", "**/__tests__/*"] From f97caa6a15e8151d7b69fe12191cb8d53db33f88 Mon Sep 17 00:00:00 2001 From: NotJayden Date: Mon, 7 Jun 2021 14:51:15 +0800 Subject: [PATCH 2/8] undo lib change --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0a9fb3b..6784221 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "osrs-json-hiscores", "version": "2.5.0", "description": "The Old School Runescape API wrapper that does more!", - "main": "lib/index", + "main": "lib/index.js", "types": "lib/index.d.ts", "files": [ "lib/**/*" From a11ac96f68e6237480e22423f1973482185dab67 Mon Sep 17 00:00:00 2001 From: NotJayden Date: Mon, 7 Jun 2021 14:53:36 +0800 Subject: [PATCH 3/8] prettier --- src/hiscores.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/hiscores.ts b/src/hiscores.ts index b1c48a8..9d99f99 100644 --- a/src/hiscores.ts +++ b/src/hiscores.ts @@ -97,8 +97,11 @@ export function parseStats(csv: string, mode: Gamemode = 'main'): Stats { return activity; }); - const filteredBosses = mode === 'seasonal'? BOSSES.filter((boss) => boss !== 'tempoross') : BOSSES; - + const filteredBosses = + mode === 'seasonal' + ? BOSSES.filter((boss) => boss !== 'tempoross') + : BOSSES; + const [leaguePoints] = activityObjects.splice(0, 1); const bhObjects = activityObjects.splice(0, BH_MODES.length); const clueObjects = activityObjects.splice(0, CLUES.length); From 4703812b5236a23b311f62bc7e27502bb3bc4cc4 Mon Sep 17 00:00:00 2001 From: NotJayden Date: Tue, 8 Jun 2021 15:49:02 +0800 Subject: [PATCH 4/8] add comment --- src/hiscores.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/hiscores.ts b/src/hiscores.ts index 9d99f99..a386937 100644 --- a/src/hiscores.ts +++ b/src/hiscores.ts @@ -96,10 +96,11 @@ export function parseStats(csv: string, mode: Gamemode = 'main'): Stats { }; return activity; }); - + + /** `seasonal` API results don't currently include TOB: Hard Mode, so it needs to be filtered out in that case. */ const filteredBosses = mode === 'seasonal' - ? BOSSES.filter((boss) => boss !== 'tempoross') + ? BOSSES.filter((boss) => boss !== 'theatreOfBloodHardMode') : BOSSES; const [leaguePoints] = activityObjects.splice(0, 1); From 14cedb5877d6e6285bc34273485713ef197f4ce7 Mon Sep 17 00:00:00 2001 From: NotJayden Date: Tue, 8 Jun 2021 16:15:36 +0800 Subject: [PATCH 5/8] add fysadStatsSeasonal.csv, update lynxTitanStats.csv, and write tests to make sure the keys for bosses match the expectation for the given gamemode --- __tests__/fysadStatsSeasonal.csv | 82 ++++++++++++++++++++++++++++++++ __tests__/hiscores.test.ts | 21 +++++++- __tests__/lynxTitanStats.csv | 5 +- 3 files changed, 104 insertions(+), 4 deletions(-) create mode 100644 __tests__/fysadStatsSeasonal.csv diff --git a/__tests__/fysadStatsSeasonal.csv b/__tests__/fysadStatsSeasonal.csv new file mode 100644 index 0000000..fb7dfd3 --- /dev/null +++ b/__tests__/fysadStatsSeasonal.csv @@ -0,0 +1,82 @@ +1,2277,4600000000 +15,99,200000000 +28,99,200000000 +18,99,200000000 +7,99,200000000 +8,99,200000000 +11,99,200000000 +32,99,200000000 +159,99,200000000 +15,99,200000000 +12,99,200000000 +9,99,200000000 +48,99,200000000 +4,99,200000000 +3,99,200000000 +25,99,200000000 +5,99,200000000 +23,99,200000000 +12,99,200000000 +2,99,200000000 +19,99,200000000 +7,99,200000000 +4,99,200000000 +4,99,200000000 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +347584,22 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 +-1,-1 \ No newline at end of file diff --git a/__tests__/hiscores.test.ts b/__tests__/hiscores.test.ts index 412a06a..6a66415 100644 --- a/__tests__/hiscores.test.ts +++ b/__tests__/hiscores.test.ts @@ -10,7 +10,8 @@ import { Stats, getPlayerTableURL, getSkillPageURL, - getStatsURL + getStatsURL, + BOSSES } from '../src/index'; const B0ATY_NAME = 'B0ATY'; @@ -19,6 +20,7 @@ const LYNX_TITAN_SPACE_NAME = 'lYnX tiTaN'; const LYNX_TITAN_UNDERSCORE_NAME = 'lYnX_tiTaN'; const LYNX_TITAN_HYPHEN_NAME = 'lYnX-tiTaN'; const LYNX_TITAN_FORMATTED_NAME = 'Lynx Titan'; +const FYSAD_FORMATTED_NAME = 'Fysad'; const attackTopPage = readFileSync(`${__dirname}/attackTopPage.html`, 'utf8'); const b0atyNamePage = readFileSync(`${__dirname}/b0atyNamePage.html`, 'utf8'); @@ -27,6 +29,7 @@ const lynxTitanNamePage = readFileSync( `${__dirname}/lynxTitanNamePage.html`, 'utf8' ); +const fysadStatsSeasonal = readFileSync(`${__dirname}/fysadStatsSeasonal.csv`, 'utf8'); jest.spyOn(axios, 'get').mockImplementation((url) => { const lynxUrls = [ @@ -46,6 +49,9 @@ jest.spyOn(axios, 'get').mockImplementation((url) => { if (getStatsURL('main', LYNX_TITAN_FORMATTED_NAME) === url) { return Promise.resolve({ status: 200, data: lynxTitanStats }); } + if (getStatsURL('seasonal', FYSAD_FORMATTED_NAME) === url) { + return Promise.resolve({ status: 200, data: lynxTitanStats }); + } throw new Error(`No mock response for URL: ${url}`); }); @@ -441,7 +447,7 @@ test('Get non-existent player', async () => { }); test('Get stats by gamemode', async () => { - const { skills } = await getStatsByGamemode(LYNX_TITAN_FORMATTED_NAME); + const { skills, bosses } = await getStatsByGamemode(LYNX_TITAN_FORMATTED_NAME); expect(skills).toMatchObject({ overall: { rank: expect.any(Number), level: 2277, xp: 4600000000 }, attack: { rank: expect.any(Number), level: 99, xp: 200000000 }, @@ -468,4 +474,15 @@ test('Get stats by gamemode', async () => { hunter: { rank: expect.any(Number), level: 99, xp: 200000000 }, construction: { rank: expect.any(Number), level: 99, xp: 200000000 } }); + + const bossKeys = Object.keys(bosses); + expect(bossKeys).toEqual(BOSSES); +}); + +test('Get stats by game mode seasonal (omit TOB: Hard Mode from bosses)', async () => { + const {bosses} = await getStatsByGamemode(FYSAD_FORMATTED_NAME, 'seasonal'); + const bossKeys = Object.keys(bosses); + + const filteredBosses = BOSSES.filter(boss => boss !== 'theatreOfBloodHardMode'); + expect(bossKeys).toEqual(filteredBosses); }); diff --git a/__tests__/lynxTitanStats.csv b/__tests__/lynxTitanStats.csv index eeb1321..fb7dfd3 100644 --- a/__tests__/lynxTitanStats.csv +++ b/__tests__/lynxTitanStats.csv @@ -15,7 +15,7 @@ 3,99,200000000 25,99,200000000 5,99,200000000 -24,99,200000000 +23,99,200000000 12,99,200000000 2,99,200000000 19,99,200000000 @@ -29,7 +29,8 @@ -1,-1 -1,-1 -1,-1 -344430,22 +347584,22 +-1,-1 -1,-1 -1,-1 -1,-1 From 90d66b6b2c69836bcb8538d57d74bb0a63f61629 Mon Sep 17 00:00:00 2001 From: NotJayden Date: Tue, 8 Jun 2021 16:16:00 +0800 Subject: [PATCH 6/8] prettier --- src/hiscores.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hiscores.ts b/src/hiscores.ts index a386937..f4ecd90 100644 --- a/src/hiscores.ts +++ b/src/hiscores.ts @@ -96,7 +96,7 @@ export function parseStats(csv: string, mode: Gamemode = 'main'): Stats { }; return activity; }); - + /** `seasonal` API results don't currently include TOB: Hard Mode, so it needs to be filtered out in that case. */ const filteredBosses = mode === 'seasonal' From f96e7e3e2d20d4c26522f6a62bdccd2aab074c61 Mon Sep 17 00:00:00 2001 From: NotJayden Date: Tue, 8 Jun 2021 16:29:43 +0800 Subject: [PATCH 7/8] check bossKeys strict equals the BOSSES array, and check seasonal bossKeys doesn't include tob hard mode --- __tests__/hiscores.test.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/__tests__/hiscores.test.ts b/__tests__/hiscores.test.ts index 6a66415..88e13c0 100644 --- a/__tests__/hiscores.test.ts +++ b/__tests__/hiscores.test.ts @@ -50,7 +50,7 @@ jest.spyOn(axios, 'get').mockImplementation((url) => { return Promise.resolve({ status: 200, data: lynxTitanStats }); } if (getStatsURL('seasonal', FYSAD_FORMATTED_NAME) === url) { - return Promise.resolve({ status: 200, data: lynxTitanStats }); + return Promise.resolve({ status: 200, data: fysadStatsSeasonal }); } throw new Error(`No mock response for URL: ${url}`); }); @@ -448,6 +448,7 @@ test('Get non-existent player', async () => { test('Get stats by gamemode', async () => { const { skills, bosses } = await getStatsByGamemode(LYNX_TITAN_FORMATTED_NAME); + expect(skills).toMatchObject({ overall: { rank: expect.any(Number), level: 2277, xp: 4600000000 }, attack: { rank: expect.any(Number), level: 99, xp: 200000000 }, @@ -476,7 +477,9 @@ test('Get stats by gamemode', async () => { }); const bossKeys = Object.keys(bosses); - expect(bossKeys).toEqual(BOSSES); + expect(bossKeys).toStrictEqual(BOSSES); + + expect.assertions(2); }); test('Get stats by game mode seasonal (omit TOB: Hard Mode from bosses)', async () => { @@ -484,5 +487,9 @@ test('Get stats by game mode seasonal (omit TOB: Hard Mode from bosses)', async const bossKeys = Object.keys(bosses); const filteredBosses = BOSSES.filter(boss => boss !== 'theatreOfBloodHardMode'); - expect(bossKeys).toEqual(filteredBosses); + + expect(bossKeys).toStrictEqual(filteredBosses); + expect(bossKeys).not.toContain('theatreOfBloodHardMode'); + + expect.assertions(2); }); From 130446ab74cd39ed97eec5d2db39f51f21c19887 Mon Sep 17 00:00:00 2001 From: NotJayden Date: Tue, 8 Jun 2021 16:36:36 +0800 Subject: [PATCH 8/8] use boss generic --- __tests__/hiscores.test.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/__tests__/hiscores.test.ts b/__tests__/hiscores.test.ts index 88e13c0..df0fe44 100644 --- a/__tests__/hiscores.test.ts +++ b/__tests__/hiscores.test.ts @@ -11,7 +11,8 @@ import { getPlayerTableURL, getSkillPageURL, getStatsURL, - BOSSES + BOSSES, + Boss } from '../src/index'; const B0ATY_NAME = 'B0ATY'; @@ -489,7 +490,7 @@ test('Get stats by game mode seasonal (omit TOB: Hard Mode from bosses)', async const filteredBosses = BOSSES.filter(boss => boss !== 'theatreOfBloodHardMode'); expect(bossKeys).toStrictEqual(filteredBosses); - expect(bossKeys).not.toContain('theatreOfBloodHardMode'); + expect(bossKeys).not.toContain('theatreOfBloodHardMode'); expect.assertions(2); });