Skip to content

Commit

Permalink
Fix: don't orphan children when filtering out parents (#989)
Browse files Browse the repository at this point in the history
  • Loading branch information
emmercm authored Mar 7, 2024
1 parent 768bfc3 commit 23e24cc
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 7 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@
"Requires ^14.18.0 || >=16.0.0 for `node:` prefixed built-in modules that many dependencies use.",
"Requires >=15.0.0 for npm v7 for package-lock.json v3 because Renovate stopped respecting the existing version in August 2023.",
"Requires ^14.18.0 || >=16.3.0 for `os.devNull`.",
"Requires >=16.16.0 for `Array.prototype.at()`."
"Requires >=16.6.0 for `Array.prototype.at()`."
],
"engines": {
"node": ">=16.6.0"
Expand Down
17 changes: 15 additions & 2 deletions src/modules/datFilter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,21 @@ export default class DATFilter extends Module {
await this.progressBar.setSymbol(ProgressBarSymbol.FILTERING);
await this.progressBar.reset(dat.getGames().length);

const filteredGames = dat.getGames()
.filter((game) => this.filterGame(game));
const filteredGames = dat.getParents().flatMap((parent) => {
const games = parent.getGames().filter((game) => this.filterGame(game));
if (games.length === parent.getGames().length) {
// Nothing was filtered, return
return games;
}

// Elect a new parent in case it was filtered out
if (games.find((game) => game.getName() === parent.getName())) {
// Parent is still present, return
return games;
}
const newParent = games.at(0)?.getName();
return games.map((game) => game.withProps({ cloneOf: newParent }));
});
const filteredDat = new LogiqxDAT(dat.getHeader(), filteredGames);

const size = filteredDat.getGames()
Expand Down
47 changes: 43 additions & 4 deletions test/modules/datFilter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ function buildDATFilter(options: OptionsProps = {}): DATFilter {
async function expectFilteredDAT(
options: OptionsProps,
gamesArr: Game[][],
expectedSize: number,
expectedGameCount: number,
): Promise<void> {
const dat = new LogiqxDAT(new Header(), gamesArr.flat());
const filteredDat = await buildDATFilter(options).filter(dat);
expect(filteredDat.getGames().length).toEqual(expectedSize);
expect(filteredDat.getGames().length).toEqual(expectedGameCount);
}

function arrayCoerce<T>(val: T | T[] | undefined): T[] {
Expand Down Expand Up @@ -56,9 +56,16 @@ function buildGameWithRegionLanguage(
releases.push(new Release(releaseName, region, language));
}

const rom = new ROM({ name: `${romName}.rom`, size: 0, crc: '00000000' });
const rom = new ROM({
name: `${romName}.rom`,
size: 0,
crc: '00000000',
});
const game = new Game({
name: romName, rom: [rom], release: releases, ...gameOptionsArr[idx],
name: `${romName}${language ? ` (${language})` : ''}`, // all games need to have unique names
rom: [rom],
release: releases,
...gameOptionsArr[idx],
});
games.push(game);
}
Expand Down Expand Up @@ -103,6 +110,38 @@ describe('filter', () => {
}, [], 0);
});

it('should not leave children abandoned', async () => {
const options = new Options({
filterRegion: ['USA', 'WORLD'],
});
const parent = new Game({ name: 'Legend of Zelda, The (Europe) (Rev 1)' });
const children = [
'Dongfang de Chuanshuo - The Hyrule Fantasy (China) (Pirate)',
'Legend of Zelda, The (Europe)',
'Legend of Zelda, The (USA)',
'Legend of Zelda, The (USA) (Rev 1)',
'Legend of Zelda, The (USA) (Rev 1) (GameCube Edition)',
'Legend of Zelda, The (USA) (GameCube Edition)',
'Legend of Zelda, The (Europe) (Rev 1) (Virtual Console)',
'Legend of Zelda, The (USA) (Rev 1) (Virtual Console)',
'Zelda no Densetsu 1 - The Hyrule Fantasy (Japan)',
].map((name) => new Game({ name, cloneOf: parent.getName() }));
const dat = new LogiqxDAT(new Header(), [parent, ...children]);
expect(dat.getParents()).toHaveLength(1);

const filteredDat = await new DATFilter(options, new ProgressBarFake()).filter(dat);

expect(filteredDat.getParents()).toHaveLength(1);
expect(filteredDat.getGames().map((game) => game.getName())).toEqual([
'Legend of Zelda, The (USA)',
'Legend of Zelda, The (USA) (Rev 1)',
'Legend of Zelda, The (USA) (Rev 1) (GameCube Edition)',
'Legend of Zelda, The (USA) (GameCube Edition)',
'Legend of Zelda, The (USA) (Rev 1) (Virtual Console)',
]);
expect(filteredDat.getGames().every((game) => game.getParent())).toEqual(true);
});

describe('filter regex', () => {
test.each([
'ONE',
Expand Down

0 comments on commit 23e24cc

Please sign in to comment.