diff --git a/__tests__/assets/replays/appbug.rec b/__tests__/assets/replays/appbug.rec new file mode 100644 index 0000000..3d6ee44 Binary files /dev/null and b/__tests__/assets/replays/appbug.rec differ diff --git a/__tests__/rec.int.test.ts b/__tests__/rec.int.test.ts index f0e3d11..fda20c0 100644 --- a/__tests__/rec.int.test.ts +++ b/__tests__/rec.int.test.ts @@ -215,6 +215,7 @@ describe('Replay', () => { ['rec_valid_1.rec', 2], ['rec_valid_2.rec', 4], ['rec_valid_3.rec', 4], + ['appbug.rec', 19], ])('.apples counts correct number of apples: %s', async (fileName, apples) => { const filePath = `__tests__/assets/replays/${fileName}`; const file = await readFile(filePath); @@ -222,6 +223,18 @@ describe('Replay', () => { expect(replay.apples).toEqual(apples); }); + test.each([ + ['rec_valid_1.rec', 2], + ['rec_valid_2.rec', 4], + ['rec_valid_3.rec', 4], + ['appbug.rec', 36], + ])('.totalApples counts correct number of apples: %s', async (fileName, apples) => { + const filePath = `__tests__/assets/replays/${fileName}`; + const file = await readFile(filePath); + const replay = Replay.from(file); + expect(replay.totalApples).toEqual(apples); + }); + test('.getTime() calculates edge case times correctly', async () => { const filePath = `__tests__/assets/replays/kelogs06vz.rec`; const file = await readFile(filePath); diff --git a/package.json b/package.json index 1b9c128..b7c29e7 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "build:umd": "webpack", "build:docs": "typedoc ./src", "test": "jest", + "test:watch": "jest --watch", "lint": "eslint src --ext .ts", "coverage": "npm run test -- --coverage", "prepublishOnly": "npm run build && npm run test" diff --git a/src/rec/Replay.ts b/src/rec/Replay.ts index 95ca8ab..522e2fd 100644 --- a/src/rec/Replay.ts +++ b/src/rec/Replay.ts @@ -282,6 +282,32 @@ export default class Replay { * @returns Number of apples */ get apples(): number { + let apples = 0; + + for (const ride of this.rides) { + const touchEvents = ride.events.filter((event) => event.type === 0); + const appleEvents = ride.events.filter((event) => event.type === 4); + const unique = [...new Set(touchEvents.map((event) => event.touchInfo))].map((event, idx) => touchEvents[idx]); + + appleEvents.forEach((appleEvent) => { + const touchEventWithSameTime = unique.findIndex((touchEvent) => { + return touchEvent.time === appleEvent.time; + }); + + if (touchEventWithSameTime > -1) { + unique.splice(touchEventWithSameTime, 1); + apples += 1; + } + }); + } + + return apples; + } + + /** + * Returns the total number of apples collected in the replay (including "apple bugs") + */ + get totalApples(): number { const apples = this.rides.reduce((apples, ride) => { apples += ride.events.filter((event) => event.type === 4).length; return apples;