From c7dc0bfd100fe47b7b2fd852b0114d284fbd11ba Mon Sep 17 00:00:00 2001 From: Christian Emmer <10749361+emmercm@users.noreply.github.com> Date: Fri, 20 Oct 2023 21:51:01 -0700 Subject: [PATCH] Update --- src/igir.ts | 2 +- src/modules/datGameInferrer.ts | 28 +++++++++------ test/igir.test.ts | 5 +-- test/modules/candidateCombiner.test.ts | 2 +- test/modules/candidatePatchGenerator.test.ts | 18 +++++----- test/modules/candidateWriter.test.ts | 9 ++--- test/modules/datGameInferrer.test.ts | 36 +++++++++++--------- 7 files changed, 57 insertions(+), 43 deletions(-) diff --git a/src/igir.ts b/src/igir.ts index 420698611..670d2d6e0 100644 --- a/src/igir.ts +++ b/src/igir.ts @@ -76,7 +76,7 @@ export default class Igir { // Set up progress bar and input for DAT processing const datProcessProgressBar = await this.logger.addProgressBar(chalk.underline('Processing DATs'), ProgressBarSymbol.NONE, dats.length); if (dats.length === 0) { - dats = new DATGameInferrer(datProcessProgressBar).infer(roms); + dats = new DATGameInferrer(this.options, datProcessProgressBar).infer(roms); } const datsToWrittenFiles = new Map(); diff --git a/src/modules/datGameInferrer.ts b/src/modules/datGameInferrer.ts index 761d819d6..dd1eccb0c 100644 --- a/src/modules/datGameInferrer.ts +++ b/src/modules/datGameInferrer.ts @@ -4,6 +4,7 @@ import moment from 'moment'; import ProgressBar from '../console/progressBar.js'; import Constants from '../constants.js'; +import ArrayPoly from '../polyfill/arrayPoly.js'; import DAT from '../types/dats/dat.js'; import Game from '../types/dats/game.js'; import Header from '../types/dats/logiqx/header.js'; @@ -22,6 +23,8 @@ import Module from './module.js'; * This class will not be run concurrently with any other class. */ export default class DATGameInferrer extends Module { + private static readonly DEFAULT_DAT_NAME = moment().format('YYYYMMDD-HHmmss'); + private readonly options: Options; constructor(options: Options, progressBar: ProgressBar) { @@ -36,14 +39,17 @@ export default class DATGameInferrer extends Module { this.progressBar.logInfo(`inferring DATs for ${romFiles.length.toLocaleString()} ROM${romFiles.length !== 1 ? 's' : ''}`); const normalizedInputPaths = this.options.getInputPaths() - .map((inputPath) => path.normalize(inputPath)); + .map((inputPath) => path.normalize(inputPath)) + // Try to strip out glob patterns + .map((inputPath) => inputPath.replace(/([\\/][?*]+)+$/, '')); const inputPathsToRomFiles = romFiles.reduce((map, file) => { const normalizedPath = file.getFilePath().normalize(); - normalizedInputPaths + const matchedInputPaths = normalizedInputPaths // `.filter()` rather than `.find()` because a file can be found in overlapping input paths, // therefore it should be counted in both - .filter((inputPath) => normalizedPath.startsWith(inputPath)) + .filter((inputPath) => normalizedPath.startsWith(inputPath)); + (matchedInputPaths.length > 0 ? matchedInputPaths : [DATGameInferrer.DEFAULT_DAT_NAME]) .forEach((inputPath) => { const datRomFiles = [...(map.get(inputPath) ?? []), file]; map.set(inputPath, datRomFiles); @@ -84,13 +90,15 @@ export default class DATGameInferrer extends Module { }, new Map()); const games = [...gameNamesToRomFiles.entries()].map(([gameName, gameRomFiles]) => { - const roms = gameRomFiles.map((romFile) => new ROM({ - name: path.basename(romFile.getExtractedFilePath()), - size: romFile.getSize(), - crc: romFile.getCrc32(), - md5: romFile.getMd5(), - sha1: romFile.getSha1(), - })); + const roms = gameRomFiles + .map((romFile) => new ROM({ + name: path.basename(romFile.getExtractedFilePath()), + size: romFile.getSize(), + crc: romFile.getCrc32(), + md5: romFile.getMd5(), + sha1: romFile.getSha1(), + })) + .filter(ArrayPoly.filterUniqueMapped((rom) => rom.getName())); return new Game({ name: gameName, description: gameName, diff --git a/test/igir.test.ts b/test/igir.test.ts index f33515420..948f43d69 100644 --- a/test/igir.test.ts +++ b/test/igir.test.ts @@ -787,8 +787,8 @@ describe('with inferred DATs', () => { [path.join('onetwothree', 'one.rom'), 'f817a89f'], [path.join('onetwothree', 'three.rom'), 'ff46c5d8'], [path.join('onetwothree', 'two.rom'), '96170874'], - ['speed_test_v51.sfc', '8beffd94'], - ['speed_test_v51.smc', '9adca6cc'], + [path.join('speed_test_v51', 'speed_test_v51.sfc'), '8beffd94'], + [path.join('speed_test_v51', 'speed_test_v51.smc'), '9adca6cc'], ['three.rom', 'ff46c5d8'], ['two.rom', '96170874'], ['unknown.rom', '377a7727'], @@ -863,6 +863,7 @@ describe('with inferred DATs', () => { ['onetwothree.zip|one.rom', 'f817a89f'], ['onetwothree.zip|three.rom', 'ff46c5d8'], ['onetwothree.zip|two.rom', '96170874'], + ['speed_test_v51.zip|speed_test_v51.sfc', '8beffd94'], ['speed_test_v51.zip|speed_test_v51.smc', '9adca6cc'], ['three.zip|three.rom', 'ff46c5d8'], ['two.zip|two.rom', '96170874'], diff --git a/test/modules/candidateCombiner.test.ts b/test/modules/candidateCombiner.test.ts index 015f8faac..4524a9415 100644 --- a/test/modules/candidateCombiner.test.ts +++ b/test/modules/candidateCombiner.test.ts @@ -18,7 +18,7 @@ async function runCombinedCandidateGenerator( romFiles: File[], ): Promise> { // Run DATInferrer, but condense all DATs down to one - const datGames = new DATGameInferrer(new ProgressBarFake()).infer(romFiles) + const datGames = new DATGameInferrer(options, new ProgressBarFake()).infer(romFiles) .flatMap((dat) => dat.getGames()); const dat = new LogiqxDAT(new Header(), datGames); diff --git a/test/modules/candidatePatchGenerator.test.ts b/test/modules/candidatePatchGenerator.test.ts index e77640824..221691762 100644 --- a/test/modules/candidatePatchGenerator.test.ts +++ b/test/modules/candidatePatchGenerator.test.ts @@ -17,8 +17,8 @@ import ReleaseCandidate from '../../src/types/releaseCandidate.js'; import ProgressBarFake from '../console/progressBarFake.js'; // Run DATInferrer, but condense all DATs down to one -function buildInferredDat(romFiles: File[]): DAT { - const datGames = new DATGameInferrer(new ProgressBarFake()).infer(romFiles) +function buildInferredDat(options: Options, romFiles: File[]): DAT { + const datGames = new DATGameInferrer(options, new ProgressBarFake()).infer(romFiles) .flatMap((dat) => dat.getGames()); return new LogiqxDAT(new Header(), datGames); } @@ -56,10 +56,11 @@ it('should do nothing with no parents', async () => { describe('with inferred DATs', () => { it('should do nothing with no relevant patches', async () => { // Given - const romFiles = await new ROMScanner(new Options({ + const options = new Options({ input: [path.join('test', 'fixtures', 'roms', 'headered')], - }), new ProgressBarFake()).scan(); - const dat = buildInferredDat(romFiles); + }); + const romFiles = await new ROMScanner(options, new ProgressBarFake()).scan(); + const dat = buildInferredDat(options, romFiles); // When const parentsToCandidates = await runPatchCandidateGenerator(dat, romFiles); @@ -72,10 +73,11 @@ describe('with inferred DATs', () => { it('should create patch candidates with relevant patches', async () => { // Given - const romFiles = await new ROMScanner(new Options({ + const options = new Options({ input: [path.join('test', 'fixtures', 'roms', 'patchable')], - }), new ProgressBarFake()).scan(); - const dat = buildInferredDat(romFiles); + }); + const romFiles = await new ROMScanner(options, new ProgressBarFake()).scan(); + const dat = buildInferredDat(options, romFiles); // When const parentsToCandidates = await runPatchCandidateGenerator(dat, romFiles); diff --git a/test/modules/candidateWriter.test.ts b/test/modules/candidateWriter.test.ts index bdce79fc9..2ae8717b7 100644 --- a/test/modules/candidateWriter.test.ts +++ b/test/modules/candidateWriter.test.ts @@ -70,9 +70,9 @@ async function walkAndStat(dirPath: string): Promise<[string, Stats][]> { ); } -function datInferrer(romFiles: File[]): DAT { +function datInferrer(options: Options, romFiles: File[]): DAT { // Run DATInferrer, but condense all DATs down to one - const datGames = new DATGameInferrer(new ProgressBarFake()).infer(romFiles) + const datGames = new DATGameInferrer(options, new ProgressBarFake()).infer(romFiles) .flatMap((dat) => dat.getGames()); // TODO(cemmer): filter to unique games / remove duplicates return new LogiqxDAT(new Header({ name: 'ROMWriter Test' }), datGames); @@ -93,7 +93,7 @@ async function romWriter( output: outputTemp, }); const romFiles = await new ROMScanner(options, new ProgressBarFake()).scan(); - const dat = datInferrer(romFiles); + const dat = datInferrer(options, romFiles); const romFilesWithHeaders = await new ROMHeaderProcessor(options, new ProgressBarFake()) .process(romFiles); const indexedRomFiles = await new FileIndexer(options, new ProgressBarFake()) @@ -551,7 +551,8 @@ describe('zip', () => { [`ROMWriter Test.zip|${path.join('onetwothree', 'one.rom')}`, 'f817a89f'], [`ROMWriter Test.zip|${path.join('onetwothree', 'three.rom')}`, 'ff46c5d8'], [`ROMWriter Test.zip|${path.join('onetwothree', 'two.rom')}`, '96170874'], - ['ROMWriter Test.zip|speed_test_v51.sfc', '8beffd94'], + [`ROMWriter Test.zip|${path.join('speed_test_v51', 'speed_test_v51.sfc')}`, '8beffd94'], + [`ROMWriter Test.zip|${path.join('speed_test_v51', 'speed_test_v51.smc')}`, '9adca6cc'], ['ROMWriter Test.zip|three.rom', 'ff46c5d8'], ['ROMWriter Test.zip|two.rom', '96170874'], ['ROMWriter Test.zip|unknown.rom', '377a7727'], diff --git a/test/modules/datGameInferrer.test.ts b/test/modules/datGameInferrer.test.ts index 0b4b17175..27295898d 100644 --- a/test/modules/datGameInferrer.test.ts +++ b/test/modules/datGameInferrer.test.ts @@ -4,30 +4,32 @@ import Options from '../../src/types/options.js'; import ProgressBarFake from '../console/progressBarFake.js'; test.each([ - ['test/fixtures/roms/**/*', { - '7z': 5, + // No input paths + [[], {}], + // One input path + [['test/fixtures/roms/**/*'], { roms: 27 }], + [['test/fixtures/roms/7z/*'], { '7z': 5 }], + [['test/fixtures/roms/rar/*'], { rar: 5 }], + [['test/fixtures/roms/raw/*'], { raw: 10 }], + [['test/fixtures/roms/tar/*'], { tar: 5 }], + [['test/fixtures/roms/zip/*'], { zip: 6 }], + // Multiple input paths + [[ + 'test/fixtures/roms/headered', + 'test/fixtures/roms/patchable/*', + 'test/fixtures/roms/unheadered/**/*', + ], { headered: 6, patchable: 9, - rar: 5, - raw: 10, - roms: 5, - tar: 5, unheadered: 1, - zip: 6, }], - ['test/fixtures/roms/7z/*', { '7z': 5 }], - ['test/fixtures/roms/rar/*', { rar: 5 }], - ['test/fixtures/roms/raw/*', { raw: 10 }], - ['test/fixtures/roms/tar/*', { tar: 5 }], - ['test/fixtures/roms/zip/*', { zip: 6 }], -])('should infer DATs: %s', async (inputGlob, expected) => { +])('should infer DATs: %s', async (input, expected) => { // Given - const romFiles = await new ROMScanner(new Options({ - input: [inputGlob], - }), new ProgressBarFake()).scan(); + const options = new Options({ input }); + const romFiles = await new ROMScanner(options, new ProgressBarFake()).scan(); // When - const dats = new DATGameInferrer(new ProgressBarFake()).infer(romFiles); + const dats = new DATGameInferrer(options, new ProgressBarFake()).infer(romFiles); // Then const datNameToGameCount = Object.fromEntries(