UNPKG

igir

Version:

🕹 A zero-setup ROM collection manager that sorts, filters, extracts or archives, patches, and reports on collections of any size on any OS.

163 lines (162 loc) • 6.15 kB
import { ProgressBarSymbol } from "../../console/progressBar.js"; import ROM from "../../models/dats/rom.js"; import { MergeMode } from "../../models/options.js"; import ArrayUtil from "../../utils/arrayUtil.js"; import IntlUtil from "../../utils/intlUtil.js"; import Module from "../module.js"; class DATMergerSplitter extends Module { options; constructor(options, progressBar) { super(progressBar, DATMergerSplitter.name); this.options = options; } /** * Un-merge, split, or merge the {@link Game}s within a {@link DAT}. */ merge(dat) { if (this.options.getMergeRoms() === void 0) { this.prefixedLogger.trace(`${dat.getName()}: no ROM merge option provided, doing nothing`); return dat; } if (!dat.hasParentCloneInfo()) { this.prefixedLogger.trace( `${dat.getName()}: DAT doesn't have parent/clone info, doing nothing` ); return dat; } const gameNamesToGames = dat.getGames().reduce((map, game) => { map.set(game.getName(), game); return map; }, /* @__PURE__ */ new Map()); this.prefixedLogger.trace( `${dat.getName()}: merging & splitting ${IntlUtil.toLocaleString(dat.getGames().length)} game${dat.getGames().length === 1 ? "" : "s"}` ); this.progressBar.setSymbol(ProgressBarSymbol.DAT_MERGE_SPLIT); this.progressBar.resetProgress(dat.getGames().length); const newGames = dat.getParents().flatMap((parent) => this.mergeParent(dat, parent, gameNamesToGames)); const newDat = dat.withGames(newGames); this.prefixedLogger.trace( `${newDat.getName()}: merged/split to ${IntlUtil.toLocaleString(newDat.getGames().length)} game${newDat.getGames().length === 1 ? "" : "s"}` ); this.prefixedLogger.trace(`${newDat.getName()}: done merging & splitting`); return newDat; } mergeParent(dat, parent, gameNamesToGames) { let games = parent.getGames(); games = games.map( (game) => game.withProps({ roms: game.getRoms().filter((rom) => rom.getStatus() !== "nodump").filter(ArrayUtil.filterUniqueMapped((rom) => rom.getName())), disks: game.getDisks().filter((disk) => disk.getStatus() !== "nodump") }) ); if (this.options.getMergeRoms() === MergeMode.FULLNONMERGED) { games = games.map( (game) => game.withProps({ roms: [ ...game.getDeviceRefs().map((deviceRef) => deviceRef.getName()).reduce(ArrayUtil.reduceUnique(), []).map((deviceRefName) => gameNamesToGames.get(deviceRefName)).filter((deviceGame) => deviceGame !== void 0).flatMap( (deviceGame) => deviceGame.getRoms().filter((rom) => rom.getStatus() !== "nodump") ), ...game.getRoms() ] }) ); } if (this.options.getMergeRoms() !== MergeMode.FULLNONMERGED) { games = games.map((game) => { if (game.getRomOf() === void 0) { return game; } let biosGame; let romOf = game.getRomOf(); while (romOf !== void 0) { const romOfGame = gameNamesToGames.get(romOf); if (romOfGame === void 0) { this.prefixedLogger.trace(`${dat.getName()}: invalid romOf: ${romOf}`); return game; } biosGame = romOfGame; romOf = biosGame.getRomOf(); } if (biosGame === void 0) { return game; } if (!biosGame.getIsBios()) { biosGame = biosGame.withProps({ roms: biosGame.getRoms().filter((rom) => rom.getBios() !== void 0) }); } return game.withProps({ roms: DATMergerSplitter.diffGameRoms(biosGame.getRoms(), game.getRoms()) }); }); } if (this.options.getMergeRoms() === MergeMode.SPLIT || this.options.getMergeRoms() === MergeMode.MERGED) { games = games.map((game) => { const cloneOf = game.getCloneOf(); if (!cloneOf) { return game; } const parentGame = gameNamesToGames.get(cloneOf); if (!parentGame) { this.prefixedLogger.trace( `${dat.getName()}: ${game.getName()} references an invalid parent: ${cloneOf}` ); return game; } return game.withProps({ roms: DATMergerSplitter.diffGameRoms(parentGame.getRoms(), game.getRoms()), disks: DATMergerSplitter.diffGameRoms(parentGame.getDisks(), game.getDisks()) }); }); } const parentGames = games.filter((game) => game.isParent()); const cloneGames = games.filter((game) => game.isClone()); if (this.options.getMergeRoms() !== MergeMode.MERGED) { if (parentGames.length > 0) { return [...parentGames, ...cloneGames]; } return cloneGames; } const cloneRoms = cloneGames.flatMap( (game) => game.getRoms().map( (rom) => new ROM({ ...rom, name: `${game.getName()}\\${rom.getName()}` }) ) ); const allRomsDeduplicated = [ ...cloneRoms, ...parentGames.flatMap((parentGame) => parentGame.getRoms()) ].filter(ArrayUtil.filterUniqueMapped((rom) => rom.hashCode())); const cloneDisks = cloneGames.flatMap((game) => game.getDisks()); const allDisksDeduplicated = [ ...cloneDisks, ...parentGames.flatMap((parentGame) => parentGame.getDisks()) ].filter(ArrayUtil.filterUniqueMapped((disk) => disk.getName())); return [ parentGames[0].withProps({ roms: allRomsDeduplicated, disks: allDisksDeduplicated }) ]; } static diffGameRoms(parentRoms, childRoms) { const parentRomNamesToHashCodes = parentRoms.reduce((map, rom) => { map.set(rom.getName(), rom.hashCode()); return map; }, /* @__PURE__ */ new Map()); return childRoms.filter((rom) => { const parentName = rom.getMerge() ?? rom.getName(); const parentHashCode = parentRomNamesToHashCodes.get(parentName); if (!parentHashCode) { return true; } return parentHashCode !== rom.hashCode(); }); } } export { DATMergerSplitter as default }; //# sourceMappingURL=datMergerSplitter.js.map