UNPKG

cbt-game-generator

Version:

Configuration generator for CBT animation apps

243 lines (201 loc) 9.15 kB
import * as fs from 'fs'; import * as path from 'path'; export class FileUpdater { constructor( private gamePath: string, private gameName: string, private numberOfVariants: number ) {} updateTypes(subLoIndex: number, isIncremental = false): void { // Skip if this is sub-lo-1 and the directory exists if (subLoIndex === 0 && this.doesSubLoDirectoryExist(1)) { return; } this.updateTagTypes(subLoIndex); } private updateTagTypes(subLoIndex: number): void { const tagTypesPath = path.join(this.gamePath, 'types', 'tagTypes.ts'); const content = fs.readFileSync(tagTypesPath, 'utf-8'); // Add new variant types const startVariant = subLoIndex * this.numberOfVariants + 1; const newTypes = Array.from({ length: this.numberOfVariants }, (_, i) => { const variantNumber = startVariant + i; return ` | I${this.gameName}<E${this.gameName}Variants.V${variantNumber}>`; }).join('\n'); // Insert new types before the closing semicolon const updatedContent = content.replace( /(\s+};)/, `${newTypes}\n$1` ); fs.writeFileSync(tagTypesPath, updatedContent); } updateConstants(subLoIndex: number, targets: string[]): void { // Skip if this is sub-lo-1 and the directory exists if (subLoIndex === 0 && this.doesSubLoDirectoryExist(1)) { return; } this.updateTargets(targets); this.updateVariantsConfig(subLoIndex, targets); } private updateTargets(targets: string[]): void { const targetsPath = path.join(this.gamePath, 'constants', 'targets.ts'); const content = fs.readFileSync(targetsPath, 'utf-8'); // Add new targets const newTargets = targets.map(target => ` ${target} = "${target}",`).join('\n'); // Insert new targets before the closing brace const updatedContent = content.replace( /(\s+})/, `${newTargets}\n$1` ); fs.writeFileSync(targetsPath, updatedContent); } private updateVariantsConfig(subLoIndex: number, targets: string[]): void { const variantsConfigPath = path.join(this.gamePath, 'constants', 'variantsConfig.ts'); const content = fs.readFileSync(variantsConfigPath, 'utf-8'); // Add new variants to the enum const startVariant = subLoIndex * this.numberOfVariants + 1; const newVariants = Array.from({ length: this.numberOfVariants }, (_, i) => { const variantNumber = startVariant + i; return ` V${variantNumber} = "${this.generateUniqueId()}",`; }).join('\n'); // Add new target-based properties const newProperties = targets.map(target => { const properties = [ ` ${target}_LOTTIE`, ` ${target}_WEBP`, ` ${target}_AUDIO`, ` ${target}_FACE_PROMPT`, ` ${target}_FACE_PROMPT_HALF` ]; return properties.join(',\n'); }).join(',\n'); // Add new config and mapping const newConfig = `export const ${this.gameName.toLowerCase()}ConfigV${subLoIndex + 1}: Record<string, any> = { ${targets.map(target => ` ${target}: "${target}",`).join('\n')} }; export const assetLottieWebpMappingSubLo${subLoIndex + 1}: Record<string, AssetsMapping[]> = { ${targets.map(target => ` ${target}: [ { backgroundWebp: "${target.toLowerCase()}.webp", lottie: "${target.toLowerCase()}.json", facePrompt: "${target.toLowerCase()}.mp4", halfFacePrompt: "${target.toLowerCase()}_half.mp4", }, ],`).join('\n')} };`; // Update content in multiple steps let updatedContent = content; // 1. Add new variants to the enum - preserve existing ones const enumMatch = content.match(/enum\s+E\w+Variants\s*{([^}]*)}/); if (enumMatch) { const existingVariants = enumMatch[1].trim(); const updatedEnum = `enum E${this.gameName}Variants {\n${existingVariants}\n${newVariants}\n}`; updatedContent = content.replace(/enum\s+E\w+Variants\s*{[^}]*}/, updatedEnum); } // 2. Add new properties - preserve existing ones const propertiesMatch = content.match(/THIS_IS_A_AUDIO,\s*([^;]*);/); if (propertiesMatch) { const existingProperties = propertiesMatch[1].trim(); const updatedProperties = `THIS_IS_A_AUDIO,\n${existingProperties},\n${newProperties};`; updatedContent = updatedContent.replace(/THIS_IS_A_AUDIO,\s*[^;]*;/, updatedProperties); } // 3. Add new config and mapping - append to existing ones updatedContent = updatedContent + '\n\n' + newConfig; fs.writeFileSync(variantsConfigPath, updatedContent); } updateMain(subLoIndex: number): void { // Skip if this is sub-lo-1 and the directory exists if (subLoIndex === 0 && this.doesSubLoDirectoryExist(1)) { return; } const mainPath = path.join(this.gamePath, 'Main.tsx'); const content = fs.readFileSync(mainPath, 'utf-8'); // Add new imports const startVariant = subLoIndex * this.numberOfVariants + 1; const newImports = Array.from({ length: this.numberOfVariants }, (_, i) => { const variantNumber = startVariant + i; return `import { ${this.gameName}V${variantNumber} } from "./configuration/variants-config/sub-lo-${subLoIndex + 1}/${this.gameName}V${variantNumber}";`; }).join('\n'); // Add new switch cases const newCases = Array.from({ length: this.numberOfVariants }, (_, i) => { const variantNumber = startVariant + i; return ` case E${this.gameName}Variants.V${variantNumber}: gameWithVariantConfig = ${this.gameName}V${variantNumber}; break;`; }).join('\n'); // Update content let updatedContent = content.replace( /(import.*\n)(export default)/, `$1${newImports}\n$2` ); updatedContent = updatedContent.replace( /(default:.*\n\s+break;)/, `${newCases}\n$1` ); fs.writeFileSync(mainPath, updatedContent); } copyAndUpdateSubLoFiles(subLoIndex: number, targets: string[]): void { // Skip if this is sub-lo-1 and the directory exists if (subLoIndex === 0 && this.doesSubLoDirectoryExist(1)) { return; } const sourceDir = path.join(this.gamePath, 'configuration', 'variants-config', 'sub-lo-1'); const targetDir = path.join(this.gamePath, 'configuration', 'variants-config', `sub-lo-${subLoIndex + 1}`); // Create target directory if it doesn't exist if (!fs.existsSync(targetDir)) { fs.mkdirSync(targetDir, { recursive: true }); } // Copy and update base config file const baseConfigSource = path.join(sourceDir, `variantsBaseConfigSubLo1.ts`); const baseConfigTarget = path.join(targetDir, `variantsBaseConfigSubLo${subLoIndex + 1}.ts`); this.copyAndUpdateBaseConfig(baseConfigSource, baseConfigTarget, subLoIndex, targets); // Copy and update variant files const startVariant = subLoIndex * this.numberOfVariants + 1; for (let i = 0; i < this.numberOfVariants; i++) { const variantNumber = startVariant + i; const sourceVariant = path.join(sourceDir, `${this.gameName}V${i + 1}.ts`); const targetVariant = path.join(targetDir, `${this.gameName}V${variantNumber}.ts`); this.copyAndUpdateVariantFile(sourceVariant, targetVariant, variantNumber, targets); } } private copyAndUpdateBaseConfig(sourcePath: string, targetPath: string, subLoIndex: number, targets: string[]): void { const content = fs.readFileSync(sourcePath, 'utf-8'); // Update the content with new sub-lo number and targets let updatedContent = content .replace(/SubLo1/g, `SubLo${subLoIndex + 1}`) .replace(/sub-lo-1/g, `sub-lo-${subLoIndex + 1}`); // Update targets in the config const targetConfig = targets.map(target => ` ${target}: "${target}",`).join('\n'); updatedContent = updatedContent.replace( /(\s+const config = {)[^}]+(\s+};)/s, `$1\n${targetConfig}$2` ); fs.writeFileSync(targetPath, updatedContent); } private copyAndUpdateVariantFile(sourcePath: string, targetPath: string, variantNumber: number, targets: string[]): void { const content = fs.readFileSync(sourcePath, 'utf-8'); // Update the content with new variant number and targets let updatedContent = content .replace(/V1/g, `V${variantNumber}`) .replace(/sub-lo-1/g, `sub-lo-${Math.floor((variantNumber - 1) / this.numberOfVariants) + 1}`); // Update targets in the variant file const targetConfig = targets.map(target => ` ${target}: "${target}",`).join('\n'); updatedContent = updatedContent.replace( /(\s+const targets = {)[^}]+(\s+};)/s, `$1\n${targetConfig}$2` ); fs.writeFileSync(targetPath, updatedContent); } private generateUniqueId(): string { const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; let result = ''; for (let i = 0; i < 8; i++) { result += chars.charAt(Math.floor(Math.random() * chars.length)); } return result; } private doesSubLoDirectoryExist(subLoIndex: number): boolean { const subLoDir = path.join(this.gamePath, 'configuration', 'variants-config', `sub-lo-${subLoIndex}`); return fs.existsSync(subLoDir); } }