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.

67 lines (66 loc) • 2.88 kB
import path from 'node:path'; import { ProgressBarSymbol } from '../../console/progressBar.js'; import GameGrouper from '../../gameGrouper.js'; import Game from '../../types/dats/game.js'; import Module from '../module.js'; /** * Merge multi-disc {@link Game}s in a {@link DAT} into one game. */ export default class DATDiscMerger extends Module { options; constructor(options, progressBar) { super(progressBar, DATDiscMerger.name); this.options = options; } /** * Merge {@link Game}s. */ merge(dat) { if (!this.options.getMergeDiscs()) { this.progressBar.logTrace(`${dat.getName()}: not merging discs`); return dat; } if (dat.getGames().length === 0) { this.progressBar.logTrace(`${dat.getName()}: no games to merge`); return dat; } this.progressBar.logTrace(`${dat.getName()}: merging ${dat.getGames().length.toLocaleString()} game${dat.getGames().length === 1 ? '' : 's'}`); this.progressBar.setSymbol(ProgressBarSymbol.DAT_MERGE_SPLIT); this.progressBar.resetProgress(dat.getGames().length); const groupedGames = this.groupGames(dat.getGames()); const newDat = dat.withGames(groupedGames); this.progressBar.logTrace(`${newDat.getName()}: merged to ${newDat.getGames().length.toLocaleString()} game${newDat.getGames().length === 1 ? '' : 's'}`); this.progressBar.logTrace(`${newDat.getName()}: done merging`); return newDat; } groupGames(games) { const gameNamesToGames = GameGrouper.groupMultiDiscGames(games, (game) => game.getName()); return [...gameNamesToGames.entries()].flatMap(([gameName, games]) => { if (games.length === 1) { return games[0]; } const roms = games.flatMap((game) => game.getRoms()); // Detect conflicting ROM names const romNamesToCount = roms.reduce((map, rom) => { map.set(rom.getName(), (map.get(rom.getName()) ?? 0) + 1); return map; }, new Map()); const duplicateRomNames = [...romNamesToCount.entries()] .filter(([, count]) => count > 1) .map(([romName]) => romName) .sort(); if (duplicateRomNames.length > 1) { // De-conflict the filenames by adding a subfolder of the original game's name const deconflictedRoms = games.flatMap((game) => game.getRoms().map((rom) => rom.withName(path.join(game.getName(), rom.getName())))); return new Game({ name: gameName, roms: deconflictedRoms, }); } return new Game({ name: gameName, roms: roms, }); }); } }