diff --git a/project/src/utils/ImporterUtil.ts b/project/src/utils/ImporterUtil.ts index 67c04b76..d9caa2d8 100644 --- a/project/src/utils/ImporterUtil.ts +++ b/project/src/utils/ImporterUtil.ts @@ -1,4 +1,5 @@ import { JsonUtil } from "@spt/utils/JsonUtil"; +import { ProgressWriter } from "@spt/utils/ProgressWriter"; import { VFS } from "@spt/utils/VFS"; import { Queue } from "@spt/utils/collections/queue/Queue"; import { inject, injectable } from "tsyringe"; @@ -119,9 +120,12 @@ export class ImporterUtil { directoriesToRead.enqueueAll(this.vfs.getDirs(directory).map((d) => `${directory}/${d}`)); } + const progressWriter = new ProgressWriter(filesToProcess.length); + while (filesToProcess.length !== 0) { const fileNode = filesToProcess.dequeue(); if (!fileNode) continue; + if (this.vfs.getFileExtension(fileNode.fileName) === "json") { const filePathAndName = `${fileNode.filePath}${fileNode.fileName}`; promises.push( @@ -135,7 +139,8 @@ export class ImporterUtil { onObjectDeserialized(filePathAndName, fileDeserialized); const strippedFilePath = this.vfs.stripExtension(filePathAndName).replace(filepath, ""); this.placeObject(fileDeserialized, strippedFilePath, result, strippablePath); - }), + }) + .then(() => progressWriter.increment()), ); } } diff --git a/project/src/utils/ProgressWriter.ts b/project/src/utils/ProgressWriter.ts new file mode 100644 index 00000000..76c5fc75 --- /dev/null +++ b/project/src/utils/ProgressWriter.ts @@ -0,0 +1,53 @@ +import * as readline from "node:readline"; + +export class ProgressWriter { + private count = 0; + private total?: number; + private done = false; + private barFillChar: string; + private barEmptyChar: string; + private maxBarLength: number; + + constructor(total: number, maxBarLength = 25, barFillChar = "\u25A0", barEmptyChar = " ") { + if (total <= 0) { + throw new Error("Total must be a positive number."); + } + if ((barFillChar && barFillChar.length !== 1) || (barEmptyChar && barEmptyChar.length !== 1)) { + throw new Error("Bar character values must be a single character."); + } + + this.total = total; + this.maxBarLength = maxBarLength; + this.barFillChar = barFillChar; + this.barEmptyChar = barEmptyChar; + } + + /** + * Increment the progress counter and update the progress bar display. + */ + public increment(): void { + if (this.done) { + return; + } + + this.count++; + + const progress = Math.floor((this.count / this.total) * 100); + const filledChars = Math.floor((progress / 100) * this.maxBarLength); + const emptyChars = this.maxBarLength - filledChars; + + const barFill = this.barFillChar.repeat(filledChars); + const barEmptySpace = this.barEmptyChar.repeat(emptyChars); + + const progressBar = ` -> ${this.count} / ${this.total} [${barFill}${barEmptySpace}] ${progress}%`; + + readline.clearLine(process.stdout, 0); + readline.cursorTo(process.stdout, 0, null); + process.stdout.write(progressBar); + + if (progress === 100) { + process.stdout.write("\n"); + this.done = true; + } + } +}